시그널 함수 signal의 선언문이 잘 이해되지 않습니다.

dltkddyd의 이미지

#include <signal.h>
void (*signal(int signum,void(*sighandler)(int)))(int);

시그널 함수의 원형이 저 위와 같다네요. 이 함수를 보건데, void(*sighandler)(int)는 분명 포인터 함수라서, 함수이름을 인자로 받을 수 있는 매개변수라는 것을 알 수 있습니다. 그런데 이해가 안 되는 부분은

void (*signal(...))(int)

에서 뒤에 있는 int 라는 부분입니다. 도대체 저 int가 왜 있는거죠? 그리고 바로 위에 언급한 함수도 포인터 함수라기에 전 이런 식이어야 한다고 생각했습니다.

void ((*singal)(...))

그런데 원형에서의 함수는 그게 아니네요. 원형에서의 signal은 다른 함수로 대체될 수 없는 형태인 것 같은데요.

dltkddyd의 이미지

void singal(int signum, void(*sighandler)(int));

이런 식이 보다 간결한 표현이 아닐지요?

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

raymundo의 이미지

이건 signal 함수의 반환형이 void 인 거고,
본문의 것은 signal 함수의 반환형이 "(int)를 인자로 받고 리턴타입이 void인 함수의 포인터"죠.

좋은 하루 되세요!

HDNua의 이미지

선언 분석은 이름을 기준으로 오른쪽에서 왼쪽으로 번갈아 진행하는데 다음과 같은 방식입니다.

int i;                i: int
int i[v1];            i: array[v1] of int
int i(t1);            i: function(t1) returning int
 
int *i;               i: pointer to int
int *i[v1];           i: array[v1] of pointer to int
int *i(t1);           i: function(t1) returning pointer to int
 
int (*i)[v1];         i: pointer to array[v1] of int
int (*i)(t1);         i: pointer to function(t1) returning int
 
int (*i[v1])[v2];     i: array[v1] of pointer to array[v2] of int
int (*i(t1))(t2);     i: function(t1) of pointer to function(t2) returning int
int (*i[v1])(t1);     i: array[v1] of pointer to function(t1) returning int
int (*i(t1))[v1];     i: function(t1) returning pointer to array[v1] of int

위 함수는,
(int 타입 인자와 "(int 타입 인자)를 받고 값을 반환하지 않는 함수"의 포인터 타입 인자)를 받아
"(int 타입 인자)를 받아 값을 반환하지 않는 함수"의 포인터를 반환
하는 함수입니다.
dcl이라는 선언 분석 프로그램을 이용해 결과를 확인하면 다음과 같이 됩니다.
signal: function(int, void (*)(int)) returning pointer to function(int) returning void

signal을 배운 적이 없지만, 이 함수는 내부적으로든 외부적으로든
void (*)(int) 타입의 값을 반환해야 하고, 이를 이용하는 것으로 보이니
값을 반환하지 않는 void 타입으로 반환형을 정하는 것도 말이 안 될 테지요.

위 내용은 The C Programming Language - Kernighan & Ritchie에 소개된 내용입니다.
163쪽의 "복잡한 선언문" 절에서 자세히 다루고 있으니 참조하세요.

저는 이렇게 생각했습니다.

dltkddyd의 이미지

제 실력이 모자라서 잘 이해가 안됩니다. 답변 올리셨는데 죄송합니다.

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

HDNua의 이미지

입력받은 인자로 함수를 결정해야 하는 경우를 예제로 만들어봤습니다.
복잡한 선언 자체에 대해 설명이 더 필요하시면 인터넷이나 다른 레퍼런스를 참조하시고,
이에 대해 이해가 됐다면 나중에 이해를 돕는 예제로 한 번 살펴보셔요.

#include <stdio.h>
#include <string.h>
 
#define STR_LEN     100
 
typedef const char *string;
 
void Swap(string *ps1, string *ps2);
void sort(string arr[], int len, int (*comp)(string, string));
int (*how_to_sort(const char sort_type[]))(string, string);
 
int NameAscending(string, string);
int LengthAscending(string, string);
 
int main(void)
{
    int i;
    char sort_type[STR_LEN];
 
    string arr[] = {
        "hello",
        "world",
        "my",
        "name",
        "is"
    };
    const int count = sizeof(arr)/sizeof(string);
    int (*comp)(string, string) = 0;
 
    printf("Enter sort way: ");
    scanf("%s", sort_type);
 
    // 함수 포인터를 입력받은 인자로 결정해야 하는 상황
    comp = how_to_sort(sort_type);
 
    if (comp==0)
    {
        fprintf(stderr, "Cannot find function %s\n", sort_type);
        return -1;
    }
 
    printf("Before sort: \n");
    for (i=0; i<count; ++i)
        printf("%d: %s\n", i, arr[i]);
 
    sort(arr, count, comp);
    printf("After sort: \n");
    for (i=0; i<count; ++i)
        printf("%d: %s\n", i, arr[i]);
 
    return 0;
}
 
void Swap(string *ps1, string *ps2)
{
    string tmp = *ps1;
    *ps1 = *ps2;
    *ps2 = tmp;
}
void sort(string arr[], int len, int (*comp)(string, string))
{
    int i, j;
    for (i=0; i<len-1; ++i)
        for (j=0; j<len-i-1; ++j)
            if (comp(arr[j], arr[j+1])>0)
                Swap(&arr[j], &arr[j+1]);
}
int (*how_to_sort(const char sort_type[]))(string, string)
{
    // 인자로 const char sort_type[]을 받고
    // int (*)(string, string)을 반환합니다.
 
    if (strcmp(sort_type, "NameAscending")==0)
        return NameAscending;
    else if (strcmp(sort_type, "LengthAscending")==0)
        return LengthAscending;
    else
        return 0;
}
 
int NameAscending(string str1, string str2)
{
    return strcmp(str1, str2);
}
int LengthAscending(string str1, string str2)
{
    return (int)(strlen(str1) - strlen(str2));
}

저는 이렇게 생각했습니다.

익명 사용자의 이미지

제일 바깥쪽은 리턴 타입입니다.
void (*)(int)

signal은 함수 이름.

signum은 첫번째 인자이름이고 int

sighandler는 두번째 인자이름인데
자료형이 void (*)(int)입니다.

typedef를 활용하면 가독성을 높힐 수 있죠

typedef void (*func_ptr)(int);
func_ptr signal(int signum, func_ptr sighandler);

댓글 달기

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