signal함수의 프로토타입은 왜 함수포인터로 되어 있을까요?

김경태의 이미지

void (*signal(int signo,void (*func)(int)))(int);

이것을 해석하면,

<integer형을 인자로 하고 return값이 없으며 (integer 하나), (integer를 인자로 하고 리턴값이 없는 handler라는 이름의 함수포인터 하나)를 인자로 하는 signal이라는 이름의 함수포인터 >

가 되는군요.

이게 사실이라면, signal은 변수이기 때문에 prototype이 맞는 경우 다른 함수를 가르킬 수도 있을 것입니다.

또한 함수포인터이므로 애초 signal.h에 signal이라는 함수를 assign하는 동작이 들어 있어야 하는데 그런 것도 않 보입니다.

이런 두가지 이유로 signal이라는 것은 함수포인터가 아닌 함수로 보이는데 분명히 선언을 보면 함수포인터로 되어 있습니다.

도대체 signal함수는 왜 함수포인터 형태로 선언되어 있을까요?

도무지 모르겠습니다. 고수님들의 현명한 조언을 기대합니다. ^^;

lyster의 이미지

해석을 잘못하셨습니다.

void (*signal(int signo,void (*func)(int)))(int);

signal의 인자
signo : func 함수 포인터에 넘겨줄 인자
func : int를 인자로 하고 리턴값이 없는 함수의 포인터

signal의 리턴값 : int를 인자로 하고 리턴값이 없는 함수의 포인터

게으름은 이제 그만

익명 사용자의 이미지

signal의 인자부분에 대한 설명은 충분히 이해가 됩니다. 그리고 함수의 리턴 값에 대한 부분도 어느정도는(?) 이해가 됩니다.

그런데 명확한 개념이 잘 않 서는군요. 함수의 리턴값에 대한 부분에 대한 설명을 조금 더 해주실 수 있는지요?

그리고 만약 signal이 함수선언이라면 signal 함수 type을 가르키는 함수 포인터를 선언한다고 가정한다면 어떤 스타일로 해야 할까요?

고수님들의 고견을 부탁드립니다.

pynoos의 이미지

typedef void (*signal_t(int signo,void (*func)(int)))(int);

signal_t func;

이렇게 하면되죠.

http://bbs.kldp.org/viewtopic.php?p=15161#15161

sangwoo의 이미지

void (*(*funcptr)(int signo, void (*func)(int)))(int)

----
Let's shut up and code.

익명 사용자의 이미지

#include <signal.h>

/* typedef void (*(*funcptr)(int signo, void (*func)(int))))(int) funcptr; */
typedef void (*SIG_TYP)(int);
typedef void (*SIG_ARG_TYP)(int);
typedef SIG_TYP (*signal_ptr)(int, SIG_ARG_TYP);

void sig_usr(int);

void sig_usr(int a)
{
        printf("signal is %d\n", a);
}

int main(void)
{
        signal_ptr funcptr_real = signal;

        funcptr_real(SIGUSR1, sig_usr);
}

질문:

위와 같은 코드를 통해서 signal type pointer to function을 만들어 내는 데는 성공했으나 위에 보시는 바 대로 세번에 걸친 typedef를 통해서 성공했을 뿐 실제 단 한번의 typedef 구문으로 전환하는 데는 실패하였습니다.

뭐가 잘못되었을까요?

주석문처리 된 문장을 통해서 signal 함수를 가리킬 수 있는 함수 타입을 정의하고 싶습니다.

고수님들의 좋은 의견 부탁드립니다. ^^;

doldori의 이미지

저 위에 pynoos님이 이미 보여주셨는데요. :)

김경태의 이미지

syntex error 납니다. *_*;

고수님들의 가르침을 기대합니다. ^^;

sangwoo의 이미지

올려주신 코드의 주석 부분의 typedef 의 문법이 틀린 것 같군요.
(괄호의 짝이 맞아야 하고, 젤 뒤의 funcptr은 없어야 합니다.)
제 테스트로는 잘 작동합니다. 실행후 kill -USR1 <pid> 로 테스트했습니다.

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

typedef void (*(*sigfunc_t)(int signo, void (*func)(int)))(int);

void
sigusr1(int arg)
{
        printf("sigusr1\n");
        return;
}

int
main(void)
{
        sigfunc_t sig_instance;
        sig_instance = signal;
        (*sig_instance)(SIGUSR1, sigusr1);
        pause();
        return (0);
}

----
Let's shut up and code.

김경태의 이미지

1. signal 함수 선언의 뜻은?

void (*signal(int signo,void (*func)(int)))(int);

예제를 void (*a)(int), a= signal(int signo, void (*handler)(int)) 두개로 나누어 봅시다.

그러면 a는 함수의 리턴벨류를 의미하며 <integer형을 argument로 하고 return 값이 없는 함수 포인터 a> 라 할수 있습니다.

근데 signal이란 놈은 <integer 하나, integer를 인자로 하고 리턴값이 없는 handler라는 이름의 함수 포인터 하나를 인자로 하는 signal이라는 이름의 함수>입니다.

이 둘을 결합하면 결국,

a = <integer형을 인자로 하고 return값이 없는 함수포인터를 리턴값으로 가지며 (integer 하나), (integer를 인자로 하고 리턴값이 없는 handler라는 이름의 함수포인터 하나)를 인자로 하는 signal이라는 이름의 함수 >입니다.

2. signal을 가르키는 함수 포인터 선언은?

위와 같이 선언자체와 리턴 값을 둘로 나누어 봅시다.

void (*) (int) -> return value;
(* signal)(int, void (*) (int)); -> return value를 제외한 함수 포인터

둘을 합하면
void (* (* signal)(int, void (*) (int)) ) (int)
와 같이 됩니다.

이것은 signal과 같은 함수를 가르킬 수 있는 함수 포인터입니다.

------------------------------------------------------------------------------------

그동안 제가 미처 모르던 부분이 아주 명확하게 이해가 되었습니다.

제가 착각했던 부분은 함수에서 함수포인터가 리턴값이 되었을 때의 선언방식이 일반 변수를 선언했을때의 그것과 다르다는 점 이었습니다.

여지껏 써왔던 함수라는 것이 함수포인터를 리턴하는 경우가 없어서 그점까지 고려하지 못했는데 상우님을 비롯한 고수님들의 친절한 조언으로 더이상 헷갈릴 일 없이 이해하게 되어 더없이 기쁘고 또 감사드립니다.

부디 행복하시고 늘 행운이 함께 하시기를 바랍니다.

^^;

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.