[완료]Pointer to function 부분에서 갑자기 혼란이 옵니다!

soratz의 이미지

안녕하세요
APUE 책을 공부하고 있는데요
문득 제 머릿속의 개념이 흔들리는 부분이 있어서
책과 인터넷을 찾아 보았으나
해결이 안되서 이렇게 질문 올립니다.

signal 부분을 보다보니

#define SIG_ERR (void (*) ())-1
#define SIG_DFL (void (*) ())0
#define SIG_IGN (void (*) ())1

이렇게 선언된 부분이 있고

"pointer to a function that takes an integer argument and returns nothing"
이렇게 되있는데요
정수를 받고 void를 리턴하는 함수라면

(void (*) (int)) 이렇게 되야 하는것 아닌지요
저 뒤에 있는 -1, 0, 1 부분이 잘 이해가 되지 않습니다.

그리고 signal 함수의 prototype을 보면
void (*signal(int signo, void (*func)(int)))(int);
이렇게 선언되어있는데
리턴값이 void를 리턴하고 int형 인자를 받는 function 인데요.
직관적으로 제일뒤에 붙은 (int)가 이해가 잘 안되네요

혹시 이 부분에 대해 참조할만한 곳이 있을까요?
부끄럽지만 시간이 되시는 분이 계시면 조언 부탁드립니다 ^^

shint의 이미지

//
http://kldp.org/node/4103

//
답변이 맞는건 같은데;;;;. 알면. 참 좋을텐데... 영어해석이 어렵네요.
http://www.velocityreviews.com/forums/t715007-re-how-to-understand-this-cpp-syntax.html

#define SIG_ERR ((void (*) ())-1)
#define SIG_DFL ((void (*) ())0)
#define SIG_IGN ((void (*) ())1)

Each definition is an integer constant expression converted,
via a cast, to a pointer-to-function type. The cast is to type
``void(*)()'', i.e., pointer to function returning void.

A modern implementation would probably define the
parameter type:

#define SIG_ERR ((void (*) (int))-1)
#define SIG_DFL ((void (*) (int))0)
#define SIG_IGN ((void (*) (int))1)

SIG_ERR, SIG_DFL, and SIG_IGN have to be function pointers, but
they merely have to be unique values; it needn't be possible to
call anything using their values. Converting a constant 0 to a
pointer-to-function type yields a null pointer, so SIG_DFL happens
to expand to an expression that evaluates to a null pointer value;
(SIG_DFL == NULL) is true. Converting any other integer value to
a pointer-to-function type yields some value that's not specified
by the standard (I'm not sure whether it's implementation-defined
or unspecified). The point is that, for the implementation for
which the above definitions were written, the three expressions
yield pointer values that are distinguishable from any pointer to
an actual function.

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

soratz의 이미지

제가 미처 함수로는 검색을 못해봤네요 죄송하고 감사합니다.
파라미터가 정해지지 않은 함수 포인터도 있다는 사실에
새삼 놀랍습니다.

그리고 정수가 함수로 캐스팅이 되는것도 몰랐네요
제 무지를 심히 반성합니다 ㅠ
좀 더 고급 책을보면 나오는 내용인가봐요

아무튼 너무 감사합니다 !

rexos33의 이미지

같은 코드라도 C++ 컴파일러로 컴파일 하면 캐스팅이 안됩니다.

즉, C 언어에서는 캐스팅 규칙이 느슨해서 가능했던 것입니다.

C++에서도 사용하려면, 님 질문에서 쓰신 것 처럼 "#define SIG_ERR (void (*) (int))1" 같이 해줘야 합니다.

모두들 행복하세요~

soratz의 이미지

이 부분이 많이 사용해보지 않아서인지 몰라도 많이 생소합니다.

또 궁금한게 있는데요 혹시 저렇게 캐스팅된 값이 어떻게 유일하다고 할수 있는거죠?
The three values used for these constants need not be -1, 0, 1. They must be three values that can
never be the address of any declarable function. 이라고 되있는데
다른 -1, 0, 1을 캐스팅한 값이 function의 주소가 되지 않는다는걸 어떻게 확신할 수 있죠?

그리고 지금 검색하다가 봤는데 함수 포인터를 2가지 방법으로 선언할 수 있다고 해서 보니
void (*pf) (int); 이 방법과
void (*) (int) pf; 이 방법이 있다고 하는데
후자는 컴파일 에러가 뜨네요 , 제가 참조한 문서가 잘못된 것인가요?

rexos33의 이미지

일반적인 OS에서 사용자 프로세스는 취할 수 없는 주소들이 있습니다. 그 중에 -1(0xffffffff) , 0(Null), 1(0x00000000) 등이 포함되겠습니다.
이 부분은 "리눅스 커널 메모리 관리" 문헌을 참고 바랍니다.

또 궁금한게 있는데요 혹시 저렇게 캐스팅된 값이 어떻게 유일하다고 할수 있는거죠?
The three values used for these constants need not be -1, 0, 1. They must be three values that can 
never be the address of any declarable function. 이라고 되있는데
다른 -1, 0, 1을 캐스팅한 값이 function의 주소가 되지 않는다는걸 어떻게 확신할 수 있죠?


두번째 방법 즉 컴파일 오류가 나는 것은 잘못 된 것입니다. 어디서 참고하신지는 모르나 인터넷의 모든 자료가 정확하다고 할 순 없습니다.
캐스팅하는 방법을 잘못 보신것 아닌가요? funcA = (void (*)(int))funcB; 처럼 말이죠.

그리고 지금 검색하다가 봤는데 함수 포인터를 2가지 방법으로 선언할 수 있다고 해서 보니
void (*pf) (int); 이 방법과
void (*) (int) pf; 이 방법이 있다고 하는데
후자는 컴파일 에러가 뜨네요 , 제가 참조한 문서가 잘못된 것인가요?

모두들 행복하세요~

mac040의 이미지

리턴된 포인터 값에 -1(0xFFFFFFFF)의 경우, 메모리 할당 방법상 당연히 불가능하니 이런식으로 사용했구나.. 생각했었는데,
구체적으로 명시되어 있는 부분이었네요..

참고로 NULL이 꼭 0은 아니라네요.

rexos33의 이미지

아래처럼 되어 있습니다...

/usr/include/asm-generic/signal-defs.h 파일:

#ifndef __ASM_GENERIC_SIGNAL_DEFS_H
#define __ASM_GENERIC_SIGNAL_DEFS_H
 
 
 
#ifndef SIG_BLOCK
#define SIG_BLOCK          0    /* for blocking signals */
#endif
#ifndef SIG_UNBLOCK
#define SIG_UNBLOCK        1    /* for unblocking signals */
#endif
#ifndef SIG_SETMASK
#define SIG_SETMASK        2    /* for setting the signal mask */
#endif
 
#ifndef __ASSEMBLY__
typedef void __signalfn_t(int);
typedef __signalfn_t *__sighandler_t;
 
typedef void __restorefn_t(void);
typedef __restorefn_t *__sigrestore_t;
 
#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
#define SIG_ERR ((__sighandler_t)-1)    /* error return from signal */
#endif
 
#endif /* __ASM_GENERIC_SIGNAL_DEFS_H */

리눅스 매뉴얼 페이지를 참고 해보면... "void ( *signal(int signum, void (*handler)(int)) ) (int);" 식의 표현은 읽기가 어려다고 하네요.

모두들 행복하세요~

soratz의 이미지

감사합니다 !
혹시 저 부분을 어떻게 찾으셨나요?

코딩하다가 궁금할때마다 함수 원형을 보려고 찾아보면
원형은 없고 extern 으로 선언된 부분만 있어서 당황한적이 많거든요
어떤 규칙같은게 있을까요?

rexos33의 이미지

아래 매뉴얼 페이지에서 SYNOPSIS 항을 보면 signal.h가 있습니다. 일반적으로 사용자 컴파일러 환경에서 헤더 파일들은 /usr/include 경로에서 찾게 됩니다.
따라서 /usr/include/signal.h에 있습니다. /usr/include 경로 밑에 하위 디렉토리들이 다수 있는데 결국 따라가다 보면 필요한 정보를 얻을 수 있습니다.

각각의 하위 디렉토리는 인터넷에서 자료를 찾으시면 참고할 만한 문헌들을 찾을 수 있을 겁니다.

$ man signal 
SIGNAL(2)                                        Linux Programmer's Manual                                       SIGNAL(2)
 
NAME
       signal - ANSI C signal handling
 
SYNOPSIS
       #include <signal.h>
 
       typedef void (*sighandler_t)(int);
 
       sighandler_t signal(int signum, sighandler_t handler);
 
DESCRIPTION
       The behavior of signal() varies across Unix versions, and has also varied historically across different versions of
       Linux.  Avoid its use: use sigaction(2) instead.  See Portability below.
 
       signal() sets the disposition of the signal signum to handler, which is either SIG_IGN, SIG_DFL, or the address  of
       a programmer-defined function (a "signal handler").
 
       If the signal signum is delivered to the process, then one of the following happens:
 
       *  If the disposition is set to SIG_IGN, then the signal is ignored.
 
       *  If the disposition is set to SIG_DFL, then the default action associated with the signal (see signal(7)) occurs.
 
       *  If the disposition is set to a function, then first either the disposition is reset to SIG_DFL, or the signal is
          blocked (see Portability below), and then handler is called with argument signum.  If invocation of the  handler
          caused the signal to be blocked, then the signal is unblocked upon return from the handler.
 
       The signals SIGKILL and SIGSTOP cannot be caught or ignored.
 
RETURN VALUE
       signal() returns the previous value of the signal handler, or SIG_ERR on error.
 
... 생략 ....

모두들 행복하세요~

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.