복잡한 함수 선언을 어떻게 이해해야 합니까?
복잡한 선언을 따르는 것을 어떻게 이해할 수 있습니까?
char (*(*f())[])();
char (*(*X[3])())[5];
void (*f)(int,void (*)());
char far *far *ptr;
typedef void (*pfun)(int,float);
int **(*f)(int**,int**(*)(int **,int **));
다른 사람들이 지적한 것처럼 cdecl은 그 일에 적합한 도구입니다.
cdecl의 도움 없이 그런 선언을 이해하고 싶다면, 안쪽에서 오른쪽에서 왼쪽으로 읽어보세요.
목록에서 하나의 임의 예제 가져오기
선언/정의되는 식별자(그리고 가장 안쪽의 식별자)인 X에서 시작합니다.
char (*(*X[3])())[5];
^
X는
X[3]
^^^
X는 삼열
(*X[3])
^ /* the parenthesis group the sub-expression */
X는 3의 배열입니다. 에 대한 지시.
(*X[3])()
^^
X는 3개의 포인터의 배열입니다. 함수는 지정되지 않은(그러나 고정된) 인수 개수를 허용합니다.
(*(*X[3])())
^ /* more grouping parenthesis */
X는 지정되지 않은(고정된) 수의 인수를 수용하는 함수에 대한 3개의 포인터 배열입니다. 그리고 포인터를 돌려주기
(*(*X[3])())[5]
^^^
X는 함수에 사용할 3개의 포인터의 배열로 불특정 다수의 인수를 허용하고 포인터를 반환합니다. 5명으로
char (*(*X[3])())[5];
^^^^ ^
X는 3개의 포인터의 배열로 기능하여 불특정 다수의 인수를 허용하고 5 char의 배열로 포인터를 반환합니다.
와 같은 .{3+5*[2+3*(x+6*2)]}=0
- 당신은 그 안에 있는 것을 해결하는 것으로 시작할 것입니다.()
그리고나서[]
y{}
:
char (*(*x())[])()
^
은.x
뭔가.
char (*(*x())[])()
^^
x
는 함수입니다.
char (*(*x())[])()
^
x
포인터를 반환합니다.
char (*(*x())[])()
^ ^^^
x
배열에 포인터를 반환합니다.
char (*(*x())[])()
^
x
포인터를 포인터 배열로 반환합니다.
char (*(*x())[])()
^ ^^^
x
함수에 대한 포인터 배열에 포인터를 반환합니다.
char (*(*x())[])()
^^^^
합니다에서 한 배열 합니다.x
는 문자를 반환하는 함수를 가리키는 함수 포인터 배열을 가리킵니다.
하지만 네, cdecl을 사용합니다.답변 확인을 위해 직접 사용했습니다 :).
만약 이것이 여전히 여러분을 혼란스럽게 하고 있다면, 종이나 좋아하는 텍스트 편집기에서 같은 작업을 해보세요.보기만 해도 무슨 뜻인지 알 길이 없습니다.
cdecl 도구의 작업처럼 들립니다.
cdecl> explain char (*(*f())[])();
declare f as function returning pointer to array of pointer to function returning char
툴 공식 홈페이지를 찾아봤지만 정품으로 보이는 홈페이지를 찾을 수 없었습니다.Linux에서는 일반적으로 도구를 포함하여 선택한 분포를 기대할 수 있으므로 위의 샘플을 생성하기 위해 설치한 것입니다.
cdecl 도구를 사용해야 합니다.대부분의 리눅스 배포판에서 사용할 수 있어야 합니다.
예를 들어 이 기능의 경우 다음을 반환합니다.
char (*(*f())[])();
의 함수 반환 포인터로 합니다를 합니다.
void (*f)(int,void (*)());
- 함수 포인터 f 의 프로토타입은 두 개의 파라미터를 취하는 함수이며, 첫 번째 파라미터는 int이고, 두 번째 파라미터는 void를 반환하는 함수의 함수 포인터입니다.
char far *far *ptr;
- ptr은 먼 포인터(일부 문자/바이트를 가리킴)를 가리키는 먼 포인터입니다.
char (*(*X[3])())[5];
5로 되돌리는 - X는할 3를 5 char합니다.
typedef void (*pfun)(int,float);
을 선언합니다.은 두 변수를 첫 두 변수는 입니다. -터 pfun합니다. pfun입니다. int는 float입니다. 다.
예.
void f1(int a, float b)
{ //do something with these numbers
};
그건 그렇고, 마지막으로 복잡한 선언은 자주 볼 수 없습니다.이를 위해 제가 방금 만든 예시가 있습니다.
int **(*f)(int**,int**(*)(int **,int **));
typedef int**(*fptr)(int **,int **);
int** f0(int **a0, int **a1)
{
printf("Complicated declarations and meaningless example!\n");
return a0;
}
int ** f1(int ** a2, fptr afptr)
{
return afptr(a2, 0);
}
int main()
{
int a3 = 5;
int * pa3 = &a3;
f = f1;
f(&pa3, f0);
return 0;
}
실제 질문은 다음과 같습니다.
포인터가 포인터를 사용하는 경우는 무엇입니까?
포인터에 대한 포인터는 T 유형의 배열이 있을 때 나타나는 경향이 있고 T 자체는 다른 것에 대한 포인터입니다.예를들면,
- C의 문자열은 무엇입니까?건입니다.
char *
. - 가끔 여러 줄의 줄을 원하십니까?그럼요.
- 하나를 어떻게 선언하시겠습니까?
char *x[10]
:x
는 10입니다에 입니다.char
, 열 줄이라고도 하죠
되면 에서가 char **
들어옵니다. .그것은 C에서 포인터 산술과 배열 사이의 매우 밀접한 관계에서 그림으로 들어갑니다.름,x
는 항상 첫 번째 요소의 포인터로 변환됩니다.
- 첫번째 요소는 무엇입니까? A.
char *
. - 첫번째 요소의 포인터가 뭐죠?
char **
.
C C ,E1[E2]
됩니다와 됩니다.*(E1 + E2)
. ,E1
예를 입니다라고 합시다.x
되는, 으로 로됩니다.char **
,그리고.E2
예를 들어 3과 같은 어떤 지수입니다. (이 규칙은 또한 이유를 설명합니다.3[x]
그리고.x[3]
동일한 것입니다.)
포인터에 대한 포인터는 어떤 유형의 동적으로 할당된 배열을 원할 때도 표시되며, 그 배열 자체가 포인터입니다.우선 T형이 뭔지 모르는 걸로 해요.
- 동적으로 할당된 T의 벡터를 원한다면 어떤 타입이 필요합니까?
T *vec
. - 할 수 죠는 ? 왜냐하면 우리는 C에서 포인터 연산을 할 수 있기 때문입니다.
T *
는 다 가 될 수 .T
기억에 남습니다 - , 와 이 를 어떻게 합니까?
n
요소?vec = malloc(n * sizeof(T))
;
이 유형의 입니다이든 입니다.T
, 그래서 그것은 사실입니다.char *
.
- 종류의 입니까
vec
한다면T
이다.char *
?char **vec
.
포인터에 대한 포인터는 유형 T의 인수 자체를 수정해야 하는 함수가 있을 때도 나타납니다.
- .
strtol
:long strtol(char *s, char **endp, int b)
. - 이게 다 무슨 일이야?
strtol
합니다에서 합니다.b
정수까지 그 요.그 끈이 얼마나 깊은지 알려주고 싶어합니다.를 둘 다할 수도 .long
그리고.char *
건 아닙니다 - 대신 반환하기 전에 수정한 문자열의 주소를 전달하여 두 번째 결과를 반환합니다.
- 끈이 또 뭐죠?래,오.
char *
. - 그래서 문자열의 주소는 무엇입니까?
char **
.
을 충분히 오래 의 도 수 있습니다.T ***
types,다를 피하기 할 수 .
마지막으로 포인터에 대한 포인터는 링크된 목록의 특정 까다로운 구현에 나타납니다.C의 이중 연결 목록의 표준 선언을 생각해 보십시오.
struct node {
struct node *next;
struct node *prev;
/* ... */
} *head;
여기서 삽입/삭제 기능을 재현하지는 않겠지만 약간의 문제가 있습니다.모든 노드는 목록의 머리 부분을 참조하지 않고 목록에서 제거할 수 있습니다(또는 그 이전에 새 노드를 삽입할 수도 있습니다).음, 어떤 마디도 아닙니다.이는 목록의 첫 번째 요소에 해당하지 않습니다.prev
입니다.이것은 당신이 목록을 개념으로 사용하는 것보다 노드 자체와 더 많이 작업하는 어떤 종류의 C 코드에서는 적당히 짜증날 수 있습니다.이는 낮은 수준의 시스템 코드에서 비교적 흔하게 발생하는 현상입니다.
요를 다시 요?node
다음과 같이:
struct node {
struct node *next;
struct node **prevp;
/* ... */
} *head;
에서,prevp
이 아니라 이전 다에 점입니다.next
포인팅합니다.첫번째 노드는?prevp
에서의 점.head
. 이와 같은 목록을 그리면(이 목록이 어떻게 작동하는지 이해하기 위해 이 목록을 그려야 함) 첫 번째 요소를 제거하거나 첫 번째 요소 앞에 새 노드를 삽입할 수 있습니다.head
x: 함수 반환 포인터를 배열[]로 되돌리는 함수 반환 char" - 응?
기능이 있습니다.
이 함수는 포인터를 반환합니다.
포인터가 배열을 가리킵니다.
해당 배열은 함수 포인터(또는 함수에 대한 포인터)의 배열입니다.
이 함수들은 char*를 반환합니다.
what's the use case for a pointer to a pointer?
하나는 인수를 통해 반환 가치를 촉진하는 것입니다.
당신이 가지고 있다고 가정해 보겠습니다.
int function(int *p)
*p = 123;
return 0; //success !
}
당신은 그것을 이렇게 부릅니다.
int x;
function(&x);
를 .function
y을 할 수 x
우리는 그것을 우리의 x에 포인터를 보내야 합니다.
에.x
라 a였습니다.char *
해요 음, 그래도 똑같네요, 우리는 그것에 대한 포인터를 넘겨야 합니다.포인터에 대한 포인터:
int function(char **p)
*p = "Hello";
return 0; //success !
}
당신은 그것을 이렇게 부릅니다.
char *x;
function(&x);
읽기 기능에 대한 Remo.D의 답변은 좋은 제안입니다.다음은 다른 사람들에 대한 몇 가지 답변입니다.
포인터를 수정할 함수에 포인터를 전달하고자 하는 경우가 하나 있습니다.예를 들어,
void foo(char **str, int len)
{
*str = malloc(len);
}
또한 문자열의 배열일 수도 있습니다.
void bar(char **strarray, int num)
{
int i;
for (i = 0; i < num; i++)
printf("%s\n", strarray[i]);
}
일반적으로 이렇게 복잡한 선언문을 사용해서는 안 되지만 함수 포인터 같은 경우에는 상당히 복잡한 유형이 필요할 때도 있습니다.이러한 경우 중간 유형에 대해 유형 디프를 사용하는 것이 훨씬 더 읽기 쉽습니다. 예를 들어 다음과 같습니다.
typedef void foofun(char**, int);
foofun *foofunptr;
또는 "함수에 포인터를 배열[]로 되돌리는 함수"의 첫 번째 예에 대해 다음과 같은 작업을 수행할 수 있습니다.
typedef char fun_returning_char();
typedef fun_returning_char *ptr_to_fun;
typedef ptr_to_fun array_of_ptrs_to_fun[];
typedef array_of_ptrs_to_fun *ptr_to_array;
ptr_to_array myfun() { /*...*/ }
만약 인 어떤 것들은 을 가질 를 들어, 이러한 하는 함수일 수 . , , 입니다, 은(의) .fun_returning_char
그럴 수도 있겠지요name_generator_type
,그리고.array_of_ptrs_to_fun
그럴 수도 있겠지요name_generator_list
두 두의 디프만 할 수 이 두 유형의 디프는 곳에서 될 수 있습니다 그래서 몇 줄을 접을 수도 있고, 두 가지 종류의 디프만 정의할 수도 있습니다. 다른 곳에서는 어떤 경우에도 유용할 것입니다.
char far *far *ptr;
이것은 MS-DOS와 윈도우 초기로 거슬러 올라가는 구식의 마이크로소프트 형태입니다.SHORT 버전은 64K 데이터 세그먼트의 어느 곳이나 가리키는 근거리 포인터와 달리, 이는 문자의 먼 포인터를 가리키는 먼 포인터라는 것입니다.완전히 뇌사 상태에 빠진 인텔 80x86 세그먼트 메모리 아키텍처를 해결하기 위한 마이크로소프트 메모리 모델에 대한 자세한 내용은 알고 싶지 않을 것입니다.
typedef void (*pfun)(int,float);
이것은 pfun을 int와 float을 취하는 프로시저에 대한 포인터의 typedef로 선언합니다.이것은 보통 함수 선언이나 프로토타입인 viz에 사용됩니다.
float foo_meister(pfun rabbitfun)
{
rabbitfun(69, 2.47);
}
우리는 모든 포인터 선언문을 왼쪽에서 오른쪽으로 평가해야 합니다. 그 문장에서 포인터 이름이나 선언 이름이 선언된 부분부터 시작해서 말이죠.
선언문을 평가하면서 가장 안쪽 괄호부터 시작해야 합니다.
포인터 이름 또는 함수 이름으로 시작하여 괄호 안의 맨 오른쪽 문자 다음에 왼쪽 문자가 이어집니다.
예:
char (*(*f())[])();
^
char (*(*f())[])();
^^^
In here f is a function name, so we have to start from that.
f.
char (*(*f())[])();
^
Here there are no declarations on the righthand side of the current
parenthesis, we do have to move to the lefthand side and take *:
char (*(*f())[])();
^
f() *
우리는 내부 괄호 문자를 완성했고, 이제 우리는 이 단계 뒤의 한 단계로 돌아가야 합니다.
char (*(*f())[])();
------
현재 괄호의 오른쪽에 있으므로 []를 사용합니다.
char (*(*f())[])();
^^
f() * []
오른쪽에 문자가 없으므로 *를 사용합니다.
char (*(*f())[])();
^
char (*(*f())[])();
^
f() * [] *
char (*(*f())[])();
다음으로 바깥쪽 열기 및 닫기 괄호를 평가합니다. 함수를 나타냅니다.
f() * [] * ()
char (*(*f())[])();
이제 문 끝에 데이터 유형을 추가할 수 있습니다.
f() * [] * () char.
char (*(*f())[])();
최종 답변:
f() * [] * () char.
f는 함수 반환 char에 대한 포인터의 배열[]에 대한 포인터를 반환하는 함수입니다.
1번과 2번은 잊어버리세요. 이것은 단지 이론적인 것입니다.
3: 됩니다에서 합니다.int main(int argc, char** argv)
. 수 .char**
첫 두 번째 , ...argv[0] , argv[1] , ...
함수에 인수로 포인터를 전달하면 함수가 가리키는 변수의 내용을 변경할 수 있으므로 함수 반환 값 이외의 방법으로 정보를 반환하는 데 유용할 수 있습니다.예를 들어 반환 값이 이미 오류/성공을 나타내는 데 사용되었거나 여러 값을 반환할 수 있습니다.호출 코드에서 이에 대한 구문은 foo(&var)이며 var의 주소, 즉 var에 대한 포인터를 사용합니다.
따라서 함수의 내용을 변경할 변수 자체가 포인터(예: 문자열)인 경우 매개 변수는 포인터에 대한 포인터로 선언됩니다.
#include <stdio.h>
char *some_defined_string = "Hello, " ;
char *alloc_string() { return "World" ; } //pretend that it's dynamically allocated
int point_me_to_the_strings(char **str1, char **str2, char **str3)
{
*str1 = some_defined_string ;
*str2 = alloc_string() ;
*str3 = "!!" ;
if (str2 != 0) {
return 0 ; //successful
} else {
return -1 ; //error
}
}
main()
{
char *s1 ; //uninitialized
char *s2 ;
char *s3 ;
int success = point_me_to_the_strings(&s1, &s2, &s3) ;
printf("%s%s%s", s1, s2, s3) ;
}
main()은 문자열에 대한 저장소를 할당하지 않으므로 point_me_to_the_strings()는 str1, str2 및 str3에 문자를 포인터로 전달하는 것처럼 쓰지 않습니다.오히려 point_me_to_the_strings()는 포인터 자체를 변경하여 다른 위치를 가리키게 하고, 포인터에 대한 포인터가 있기 때문에 이렇게 할 수 있습니다.
웹상에서 발견한 거의 모든 설명이 혼란을 해소하지 못했기 때문에 선언에 대한 생각을 추가해야겠다고 생각했습니다.
가장 먼저 해야 할 일은 선언자에서 지정자 순서를 분리하는 것입니다.
지정자 시퀀스에는 다음과 같은 키워드만 포함됩니다.const
,volatile
,inline
과 , 와 .int
,char
,unsigned long
. .. 절대 괄호를 포함하지 않을 것입니다.(
)
, [
]
, *
, 아니면 이름을 신고할 수도 있습니다.
선언자 OTOH는 항상 선언될 엔티티의 (사용자가 제공한) 이름을 포함하며, 선택적으로 괄호와 같은 다른 기호로 둘러싸여 있습니다.(
)
, [
]
, *
s. 일반화된 변수, 배열, 포인터 또는 함수를 지칭할 때 엔티티라는 단어를 사용하고 있습니다.
지정자 시퀀스의 유형 지정 키워드는 선언에서 명명된 것(선언된 개체)을 참조하지 않습니다.이들은 선언자의 결과인 지정된 개체를 가리킵니다.
아래는 예시입니다.
const char *names[10];
헤어졌어요...
const char *names[10] ;
^^^^^^^^^^ ^^^^^^^^^^
|-spec-seq-||-declrtor-|
const char
선언된 엔티티를 참조하지 않습니다. names
. 선언자의 결과인 지정된 엔티티를 가리킵니다. *names[10]
.
지정된 엔티티 유형에서 선언된 엔티티 유형을 얻기 위해 선언된 이름에서 시작하여 뒤로 작업합니다.작업 순서에 따라 별표 앞에 인접한 괄호를 읽습니다.names[10]
해야 한다고 .names
그리고 0과 9사이의 오프셋에서 일부 요소를 선택합니다.*names[10]
선택한 요소를 삭제한다고 합니다.
먼저 0과 9 사이의 오프셋에서 원소를 선택하고, 두 번째로 방금 선택한 것을 역참조하기 때문에 다음과 같이 결정했습니다.names
지정한 엔터티 유형에 대한 포인터를 포함하는 길이 10의 배열이어야 합니다.
이 됩니다(으)로 됩니다.const char
.
이 내용을 종합하면, 선언문은 ...로 읽혀져야 합니다.
합니다.
names
열에 배열 10 10)const char
.
그 대신에 우리가...
const char (*names)[10];
연산 순서를 보면 괄호 안에 있는 것을 먼저 한다고 되어 있어서 그래서.(*names)[10]
먼저, 역참조라고 말합니다.names
, 둘째, 0과 9 사이의 간격띄우기에서 요소를 선택합니다.
.names
이제 지정된 엔티티의 배열에 대한 포인터입니다.다입니다.const char
을...라고.라고 읽었습니다.
합니다.
names
열의 이 10)const char
.
이제 우리가...
const char *const names[10];
는.const
별표 바로 뒤에 나타날 때 선언자 내부에 나타날 수 있습니다.,입니다,즉에서되는 메모리 하다는 뜻입니다.상수 포인터를 선언하는 방법입니다.그 선언문에는 ...라고 적혀 있습니다.
합니다.
names
열 배열(10)로서 10)const
시에 대한 사항const char
.
이제 이 변수는 10개의 문자열 리터럴 목록으로 초기화해야 합니다.
이제 함수 선언을 고려해 보겠습니다.
int foo(const char **);
함수 선언은 익명의 선언이기는 하지만, 인수 목록에 있는 각 인수가 다른 선언이라는 점에서 변수 선언과 다릅니다.
먼저 논쟁을 알아보겠습니다.
const char **
선언문은 익명이기 때문에, 더 잘 이해하기 위해서는 이름이 보통 있을 법한 곳에 정신적으로 무언가를 삽입해야 합니다.
const char **_anon_
만약 우리가 언급을 취소한다면_anon_
지정된 개체를 두 번 받으면 됩니다.입니다 입니다.const char
일 수 이름의 배열일 수 있습니다.
이제 완전한 선언자를 생각해보세요...
foo(const char **);
입니다.foo
를 합니다"에합니다.foo
", "를 합니다.foo
는 함수입니다.입니다에서 입니다.foo
.
그러므로...
int foo(const char **);
...라고 읽힐 수 있습니다.
합니다.
foo
로서 로서 터]합니다에 를 표시하는]합니다.const char
및 ]]int
.
이제 생각해보세요...
int (*foo)(const char **);
는.(*foo)(const char **)
먼저, 역참조라고 말합니다.foo
, 둘째, 포인터에 포인터를 입력할 유형 - 포인터의 인수를 전달합니다.const char
.foo
논의가 전달되기 전에 기각되어야 합니다.foo
는 이제 함수의 포인터입니다.따라서 그 선언은...
합니다.
foo
로서 서에 합니다]로에 대한 포인터의 인수를const char
및 ]]int
.
이제 괄호가 없는 경우를 생각해 보십시오.
int *foo(const char **);
작업 순서가 다르기 때문에 의미가 완전히 바뀝니다.이제 먼저 포인터를 가리키는 유형 - 포인터의 인수를 전달합니다.const char
~에게foo
, 그런 다음, 반환 값을 역참조하여 다음을 구합니다.int
.
은 을 의미합니다.foo
는 함수에 대한 포인터가 아니라 함수에 대한 포인터를 반환하는 함수입니다.int
완전한 와 같이 되어 있습니다 따라서 완전한 선언은...
합니다.
foo
터]합니다에 를 표시하는] 합니다.const char
및 터로 를및합니다. [int합니다]합니다.
그럼 이건...
int (*foo(const char **))();
이전과 마찬가지로, 논쟁은 다음으로 넘어갔습니다.foo
투 투는"낼 포인터.const char
가 ". 하십시오"에 할 때 foo
다를 .int
은 . .int
은 .foo
더 .int
를 , .int
.
하자면,int (*foo(const char **))(double)
는 함수 포인터를 반환하는 함수의 선언입니다.그 선언은 ...로 읽힙니다.
합니다.
foo
로서 로서 터]합니다에 를 표시하는]합니다.const char
및[ . ]및 returning type [환 type int.
이제 내가 생각해낼 수 있는 가장 끔찍한 혐오스러운 선언입니다.이 IRL과 같은 것은 절대 볼 수 없을 것이지만 연습을 위해 읽을 수 있다면 거의 모든 것을 읽을 수 있을 것입니다.
const char *const (*foo(int *[4], int (*)(const char *)))(double *(*)[]);
제정신을 유지하려면, 우리는 이것을 부분적으로 쪼개서 내부에서부터 시작해야 합니다.
먼저 밑줄 친 이 문구를 단독으로 보세요.
const char *const (*foo(int *[4], int (*)(const char *)))(double *(*)[]);
^^^^^^^^
이 .*
고.[
은, 선언입니다.int *_anon_[4]
3를 . 가 0 3 에서 ._anon_
하면,int
친 읽습니다 그래서 밑줄 친 문구를 다음과 같이 읽습니다.
에 4)
int
.
이제 밑줄 친 이 문구를 생각해 보세요.
const char *const (*foo(int *[4], int (*)(const char *)))(double *(*)[]);
^^^^^^^^^^^^^^^^^^^^^
.*
인에(*)
에 에도 말입니다*
인에(const char*)
먼저 안쪽 문구를 읽어보도록 하겠습니다.
const char *_anon_
_anon_
을 주다const char
말이야, ㅇconst char *
냥".const char
전체 친 ." 이제 전체 밑줄 친 문구로 넘어가겠습니다.
int (*_anon_)(const char *)
만약 우리가 언급을 취소한다면_anon_
로, 포인터 합니다"를 전달합니다.const char
으로서, 을 됩니다.int
"..."라는 가 있습니다.int (*)(const char*)
읽다...
[에 [에]
const char
.]int
이제 하나 더 내면의 문구.
const char *const (*foo(int *[4], int (*)(const char *)))(double *(*)[]);
^^^^^^^^^^^^^
은 에 합니다.double *(*_anon_)[]
는 참조를 취소합니다._anon_
그런 으로 해당 를 다 됩니다.double
가.double *(*)[]
이렇게 읽힙니다...
() 를
double
이제 전체 선언을 다시 생각해 보십시오.
const char *const (*foo(int *[4], int (*)(const char *)))(double *(*)[]);
단순화하기 위해 이미 해독한 구문을 레이블로 바꿉니다.
const char *const (*foo([...1...],[...2...]))([...3...]);
가 논쟁을 한다면 한다면.[...1...]
그리고.[...2...]
.foo
로 전달한 [...3...] 의 수 .const char
.
이것은 완전한 선언이...
합니다.
foo
및 [...3...] 인수를 로서 [...1...], [...2...]고 [...3...]고 []합니다를 합니다.const
const char
] ].
아니면...
합니다.
foo
열 기합니다 4)]형에 4.int
[ [ , 및에 대한 ] 용] [const char
.]int
크기)], [수에 ]], [터]] [기환)]][[함수 ]]로를 반환합니다.double
는로const
const char
] ].
그렇게foo
에 대한 .int
함수 포인터를 인수로 지정하고 다른 함수 포인터를 반환합니다.두 함수 포인터의 인수와 반환 값을 지정해야 하는 필요성은 선언을 엄청나게 복잡하게 만듭니다.
언급URL : https://stackoverflow.com/questions/1448849/how-do-i-understand-complicated-function-declarations
'programing' 카테고리의 다른 글
해당 루프의 함수 내에서 루프를 탈출하는 것 (0) | 2023.10.12 |
---|---|
현재 지점을 제외한 모든 지역 지점을 삭제할 수 있습니까? (0) | 2023.10.12 |
Visual Studio 2012의 디버그 .NET Framework 소스 코드? (0) | 2023.10.12 |
논증 평가란 무엇입니까? (0) | 2023.10.12 |
데이터베이스에 비즈니스 로직 저장 (0) | 2023.10.12 |