[질문]소스에서 구문에 대한 궁금증

익명 사용자의 이미지

어떤 소스를 보니 아래와 같은 표현이 있은데 이것이 맞는 표현인지 또 어떤 식으로 해석을 해야할지 모르겠습니다.

typedef int Myfunc(const char*, const struct stat*, int);
static Myfunc myfunc
static int myftw(char *, Myfunc *);
static int dopath(Myfunc *);

이렇게 되있는데 의문점이 integer를 Myfunc 함수로 타입 디파인 해주었다고 하더라도
함수명만 따로 따와서 데이터 형처럼 변수 앞에 놓는 것이 가능한 표현인가요?
그렇다면 변수 myfunc은 어떤 데이터형으로 정의 된다는 것인가요?
그리고 아래 두개의 프로토 타입에서는 한 술 더떠서 아규먼트를 포인터 형으로 선언했는데
이것도 가능한건가요?

익명 사용자의 이미지


가능합니다.

myfunc 는 함수 포인터 입니다.

따라서

dopath( myfunc ); 라고 사용합니다.

익명 사용자의 이미지

하얀눈 wrote..

가능합니다.

myfunc 는 함수 포인터 입니다.

myfunc는 함수 포인터가 아니라 함수입니다.

따라서

dopath( myfunc ); 라고 사용합니다.
이건 맞습니다.

익명 사용자의 이미지

구문 wrote..
어떤 소스를 보니 아래와 같은 표현이 있은데 이것이 맞는 표현인지 또 어떤 식으로 해석을 해야할지 모르겠습니다.

typedef int Myfunc(const char*, const struct stat*, int);
static Myfunc myfunc
static int myftw(char *, Myfunc *);
static int dopath(Myfunc *);

static Myfunc myfunc에 세미콜론만 덧붙인다면 옳습니다 )

이렇게 되있는데 의문점이 integer를 Myfunc 함수로 타입 디파인 해주었 다고 하더라도
함수명만 따로 따와서 데이터 형처럼 변수 앞에 놓는 것이 가능한 표현 인가요?
그렇다면 변수 myfunc은 어떤 데이터형으로 정의 된다는 것인가요?
그리고 아래 두개의 프로토 타입에서는 한 술 더떠서 아규먼트를 포인 터 형으로 선언했는데
이것도 가능한건가요?

먼저 typedef의 용법을 모르시는것 같습니다..

typedef에 대해서 말씀드리자면..

이건 절대로 #define과 같은 형식을 따르지 않습니다..

한마디로 #define A B같이 A를 B로 정의한다는 형식이 아니란 뜻입니다..

typedef를 사용할 때는..

먼저 typedef를 앞에 쓰고 그 뒤에 어떤 변수를 선언하는 것 처럼 하시면

됩니다..

예를 들어 char *를 pChar란 형으로 정의하고 싶으면

먼저 pChar를 그냥 변수명으로 생각하시고 선언을 하신 뒤에

--> char *pChar;

앞에다가 typedef를 붙이시면 됩니다.

--> typedef char *pChar;

이제 이 정의된 데이터형을 써먹어보면..

pChar a;

이렇게 한다면 char *a;랑 같은거죠..

이번에는 함수 포인터를 예로 들어보죠..

double형을 반환하고 두개의 int형의 인자를 취하는 함수에 대한

함수포인터를 만들어보면..

--> double (*pFunc)(int, int);

이 되죠..

그런데 만약 앞에다가 typedef를 붙이면

--> typedef double (*pFunc)(int, int);

이제 pFunc는 새로운 데이터 형이 된 거죠..

pFunc p; 이렇게 하면

double (*p)(int, int); 하는거랑 같아지죠..

그럼 만약에 pFunc *p;이렇게 하면 어떻게 해석이 되느냐 하면..

pFunc의 정의 typedef double (*pFunc)(int, int);

에서 pFunc의 자리에 (*p)를 집어 넣으시면 됩니다..

--> typedef double (*(*p))(int, int);

여기서는 꼭 괄호가 필요가 없죠..--> typedef double (**p)(int, int);

이제 님께서 물어보신 것을 예로 들어보면..

typedef int Myfunc(const char*, const struct stat*, int);

여기서 typedef를 빼면 그냥 단순한 어떤 함수의 선언이죠?

typedef를 넣으면 Myfunc가 새로운 형이 됩니다..

static Myfunc myfunc;

이것을 해석하기 위해서는

myfunc를 위의 typedef int Myfunc........에서

Myfunc 자리에 넣어보세요

--> static int myfunc(const char*, const struct stat*, int);

결국 바로 위의 것과 같습니다..

static int dopath(Myfunc *);

이번에는 편의를 위해 Myfunc *대신에 Myfunc *p라고 생각하면
(함수선언에서는 써주나 안써주나 상관없는것 아시죠? ) )

static int dopath(Myfunc *p);가 되죠

역시 typedef int Myfunc(const char*, const struct stat*, int);

에서 Myfunc자리에 (*p)를 집어 넣어보면( *p가 아니라 꼭 (*p)로

넣어서 해석해야 합니다!!!!)

int (*p)(const char*, const struct stat*, int);

이렇게 되죠? 한마디로 여기서 p는 함수포인터가 되는거죠..

이제 완전하게 써보면..

static int dopath(int (*p)(const char*, const struct stat*, int));

이렇게 됩니다.

결국 dopath함수는 함수포인터를 인자로 취하는 거죠..

도움이 많이 되었으면 합니다..

익명 사용자의 이미지

흠.. wrote..
하얀눈 wrote..

가능합니다.

myfunc 는 함수 포인터 입니다.

myfunc는 함수 포인터가 아니라 함수입니다.

따라서

dopath( myfunc ); 라고 사용합니다.
이건 맞습니다.

냠..ㅡ,.ㅡ;;
컴파일러가 둘다 맞다고 하니 어쩔수 없지만..
대충 예제를 만들어보면 아래 처럼해야 바른표현이 될꺼 같은데..
예제에서 static Myfunc *myfunc 처럼 해야 바른표현이고..
이걸 한번 생각해보시죠..
int func( void ) 를 선언후 func 만 쓰면 이것은 함수 입니까
아니면 함수포인터 일까요.. 다시말해서 함수란 반드시 뒤에 () 가붙어야
함수지 그렇지 않으면 함수 포인터 인것입니다.
그리고 func 의 값을 출력해보면 분명 번지 가 나옵니다.

typedef int Myfunc(void);
static Myfunc *myfunc;
int dopath(Myfunc *a);

int func( void )
{
printf( "kk \n" );
return 0;
}

int dopath( Myfunc *a )
{
printf( "%p\n", a );
a();
return 0;
}

int main( void )
{
dopath( func );

return 0;
}

이것도 보시면......

typedef int Myfunc(void);
static Myfunc myfunc;

int myfunc( void )
{
printf( "myfunc\n" );
return 0;
}

int main( void )
{

printf( "[%p], [%p] \n", myfunc, &myfunc );

return 0;
}

출력 결과 값은 같습니다.

~

익명 사용자의 이미지

함수명 자체가 자기가 나타내는 루틴의 주소를 가지고 있는 건

당연하구요..

하얀눈님께서는 함수명 자체가 주소를 가지고 있으므로 함수포인터라고

생각하시는 모양인데..

포인터라는 것은 단순히 주소를 가지고 있다고 해서 포인터인것은

아닙니다..

임의로 무엇인가를 가리킬 수 있어야 합니다. 그래야 포인터가 되는거죠.

예를 들어보겠습니다.

char *p;
char a[10];

여기서 p는 포인터지요?

a는 10바이트 크기 배열의 첫번째 주소를 가지고 있지요?

그러면 여기서 a가 어떤 주소를 가지고 있다고 해서 포인터라고 할 수 있
나요?

아니지요. a는 상수이므로 어떤 값을 집어 넣을 수 없습니다.

그냥 array지요..

함수 포인터도 똑같습니다.

함수명은 마치 배열과 같이 어떤 정해진 주소를 가지고 있는 상수이고

함수포인터는 어떤 함수를 가리킬 수 있는 "변수"입니다.(포인터)

익명 사용자의 이미지


님 말이 맞군요..

이제 기본개념도 오락가락하니 벌써 머리가 굳어가나 봅니다.ㅡㅡ;

익명 사용자의 이미지


올리신 글 보고,

배열은 sizeof() 를 때리면 배열이 잡고 있는 공간의 크기가 나오고,
포인터는 포인터를 저장할 공간 크기가 나온다는데 생각이 미쳐서
함수를 sizeof() 때려보면 어떨까 했는데,,
여러분들 어떻게 생각하세요?

아래 코드를 수행시켜봤는데
(환경
% uname -a
SunOS xxx 5.5.1 Generic_103640-29 sun4m sparc sun4m
% gcc --version
2.7.2
)

#include

typedef int Myfunc(const char*, int);
Myfunc myfunc;
Myfunc *fp;

int
myfunc(const char *s, int x)
{
int y;
int z;
int a[10];
int b[10];

printf("haha\n");
printf("hoho\n");

return 0;
}

int
main(int argc, char **argv)
{
int j;

printf("function size is %d.\n", sizeof(myfunc));
printf("function pointer size is %d.\n", sizeof(fp));
}

결과가

% a.out
function size is 1.
function pointer size is 4.

처럼 나오네요. ^^

typedef 에는 struct 도 있고 하는데,
헤더 인클루드 안해서 오류가 발생해서 귀찮아서 뺐습니다.
(생각해 보니 뺀게 더 귀찮았던 것 같기도 한데..)

myfunc 함수 정의에는 변수를 더 정의해보거나 덜 정의해도
결과는 동일했었네요.

C++ 이면 결과가 좀 틀릴까요?

이 결과를 해석할 수 있는 언어정의 있는 곳 알려주심
고맙겠습니다.

익명 사용자의 이미지

K&R 책에서 sizeof 부분을 뒤져보니(2nd edition,204페이지)

이렇게 나와있네요

sizeof operator
The sizeof operator yields the number of bytes required to store
an object of the type of its operand. The operand is either an
expression, which is not evaluated, or a parenthesized type name.
When sizeof is applied to a char, the result is 1; when applied to
an array, the result is the total number of bytes in the array. When
applied to a structure or union, the result is the number of bytes
in the object, including any padding required to make the object
tile an array the size of an array of n elements is n times the
size of one element.
The operator may not be applied to an operand of function type, or
of incomplete type, or to a bit-field. The result is an unsigned
integral constant; the particular type is implementation-defined.
The standard header defines this type as size_t.

위에서 보듯이 function type에는 sizeof가 적용이 될수 없다고 하네요.

gcc가 그냥 편의상 sizeof(function type)을 1로 정의하는 것 같습니다.

댓글 달기

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