복합 C 선언
인터넷에서 코드 몇 개를 검색하던 중 이런 걸 발견했어.
float * (*(*foo())[SIZE][SIZE])()
이 선언문을 어떻게 읽을까?그러한 복잡한 선언문을 읽기 위한 특정한 규칙들이 있는가?
표준 규칙: 가장 왼쪽의 식별자를 찾아 다음을 기억하면서 빠져나갈 수 있는 방법을 강구하십시오.[]
그리고()
앞에 묶다.*
:
foo -- foo
foo() -- is a function
*foo() -- returning a pointer
(*foo())[SIZE] -- to a SIZE-element array
(*foo())[SIZE][SIZE] -- of SIZE-element arrays
*(*foo())[SIZE][SIZE] -- of pointers
(*(*foo())[SIZE][SIZE])() -- to functions
* (*(*foo())[SIZE][SIZE])() -- returning pointers
float * (*(*foo())[SIZE][SIZE])(); -- to float
당신이 쟈, 여분이에게 있다고 .float
:
float *quux();
float *bar();
float *bletch();
float *blurga();
2x2 테이블에 저장한다고 가정해 봅시다.
float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
tab
x로 포인망으로 을 할 수 있다.float
.
이제 그 테이블에 포인터를 돌려주는 기능을 원한다고 결정합시다.
float *(*(*foo())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
return &tab;
}
다른 기능의 테이블을 빌드하거나 동일한 기능을 다르게 구성하는 여러 기능을 사용할 수 있다는 점에 유의하십시오.
float *(*(*qwerbl())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
return tab;
}
내가 이런 일을 할 수 있는 유일한 이유야이런 활자는 야생에서 아주 자주 보아서는 안 된다(비슷하게 잘 자라서, 나도 비슷한 악랄한 글을 쓴 죄를 지었지만).
위의 답변들은 대부분 충분히 훌륭하지만, 복잡한 C 선언문을 해독하기 위한 완전한 규칙 집합이 부족하다.나는 복잡한 C 선언문을 해독하기 위해 아래에 완전한 세트를 제공했다.이 규칙 집합은 실제로 운영자의 우선 순위에 기초한다.오른손 나선형 규칙과 같은 규칙은 이러한 규칙들의 집합에 대한 지름길이라고 생각할 수 있다.
무엇보다도 우리는 그 선언을 해독하기 위해 몇 가지를 알아야 한다.
선언문의 '기본형'
C 선언은 항상 하나의 기본 선언 유형을 가지고 있다.이것은 선언의 가장 왼쪽 위치에 있다.예를 들어 -
int a
기기는 'int'float *p
기기는 'float'char (*p)[3]
기기는 '차르'
우선순위 및 연관성
다음으로 우리는 의 우선 순위를 알아야 한다.()
[]
그리고*
- 참조 해제 연산자
()
[]
- 연관성은 왼쪽에서 오른쪽으로*
- 연관성은 오른쪽에서 왼쪽으로
위의 각 연산자에 해당하는 구문
다음으로 각 연산자에 해당하는 디코딩된 구문을 알아야 한다.앞의 예들을 보면 이 점을 분명히 알 수 있을 것이다.
()
가능[SIZE]
SIZE 배열의*
- 에 대한 포인터
이제 선언문을 해독하려면 아래의 규칙을 따르십시오.
항상 변수 이름 다음에 'is'를 쓰십시오.
예를 들어 -
int a
- a는 …이다.float *p
- p는...char (*p)[3]
- p는...
항상 기본 유형으로 끝내기
예를 들어 -
int a
- a는 …이다.인트로float *p
- p는...둥둥 뜨다char (*p)[3]
- p는...마를 뜨다
이제 다음 하위 단계를 사용하여 중간 부분을 채우십시오.
이름에서 시작하여 연산자 우선 순위 및 연관성을 따라 차상위 연산자를 선택하고 이에 해당하는 구문을 디코딩된 문자열의 중간 부분에 추가한다.
디코딩 프로세스가 완료될 때까지 나머지 선언에 대해 위의 하위 단계를 반복하십시오.
비고 1: 단순성을 위해 함수의 인수는 무시했지만, 함수의 인수는 다음과 같은 구문 바로 뒤에 포함될 수 있다.()
.
참고 2: 괄호()()
연산자의 우선순위를 다른 산술식처럼 변경한다.
비고 3: 해독된 선언에서 괄호를 사용하여 가독성을 높일 수 있다(아래 몇 가지 예에서 나는 그것을 했다).()의 각 세트를 하나의 단위로 생각하라.
참고 4: n차원 배열은 실제로 ... (n-1회) 배열의 배열이다.ex - int A[2][3] - A는 2의 배열이다(3 int의 배열). 즉, A는 각 요소가 3개의 정수를 포함하는 배열인 2개의 원소의 배열이다.
예
int a
- a는 intfloat *p
- p는 플로트에 대한 포인터임char (*p)[3]
- p는 3자 배열의 포인터임
몇 가지 복잡한 선언 사례
int **p[10]
- p는 포인터에서 int에 이르는 10개의 포인터 배열이다.int (*p)[10]
- p는 10 int 배열에 대한 포인터임int *p(char *a)
- p는 포인터를 int로 되돌리는 기능이다.int (*p(char*a))[10]
10p는 기고(10 int)로 한다.int *(*p)()
복귀(p는 (기)의 대인(int)에 대한 다.int (*p()[20])[10]
p는 는(배열 20 (10 int))이다.
이 규칙 집합은 다음에서 사용할 수 있다.const
또한 - const 한정자는 용어를 왼쪽(있는 경우)으로 수정한다. 그렇지 않으면 오른쪽(있는 경우)으로 수정한다.
const int *p[10]
- p는 int const에 대한 10개의 포인터 배열이다.int const *p[10]
- p는 const에 대한 10개의 포인터 배열이다(7번째 예와 동일).int *const p[10]
한 것이다.
이제 실제로 그 용도를 어디서도 찾을 수 없지만 그럼에도 불구하고 디코딩 과정을 증명하는 데 사용될 수 있는 정말 복잡한 예시
char *(*(**foo[][8])())[]
- foo의 배열은 (8 ~ (기능 복귀)(((와)의 배열))))))이다.
이제 마침내 그 질문에 주어진 선언문을 해독했다.
float * (*(*foo())[SIZE][SIZE])()
- foo는 기능 복귀 (SIZE 배열 (SIZE 배열 (점화 포인터에서 플로트로 복귀하는 기능))))
다음은 내가 이 디코딩 과정을 읽은 기사의 링크다.
예 10은 이 기사에서 가져온 것이다.
http://www.unixwiz.net/techtips/reading-cdecl.html
나 이거 안 한 지 꽤 오랜만이야!
시작foo
오른쪽으로 가십시오.
float * (*(*
foo()
)[SIZE][SIZE])()
foo는 논거가 없는 함수다...
닫히는 괄호가 있어서 제대로 갈 수가 없어.왼쪽으로 이동:
float * (*(
* foo()
)[SIZE][SIZE])()
foo는 포인터를 반환하는 인수가 없는 함수다.
더 이상 왼쪽으로 갈 수 없으니 괄호를 건너서 다시 오른쪽으로 가자.
float * (*
(* foo())
[SIZE][SIZE])()
float * (*
(* foo())[SIZE]
[SIZE])()
float * (*
(* foo())[SIZE][SIZE]
)()
foo는 인수가 없는 함수로서 SIZE...의 SIZE 배열 배열로 포인터를 되돌린다.
닫기 괄호 도달, 포인터 기호에 도달하려면 다시 왼쪽으로 이동:
float * (
*(* foo())[SIZE][SIZE]
)()
foo는 인수가 없는 함수로, SIZE 포인터의 배열로 포인터를 돌려주는 SIZE 포인터들을 ...에게...
왼쪽 괄호 다시 교차해서 오른쪽으로 다시 가보자.
float *
( *(* foo())[SIZE][SIZE])
()
float *
( *(* foo())[SIZE][SIZE])()
foo는 인수가 없는 함수로서 SIZE 포인터의 배열인 SIZE 포인터로 포인터를 인수가 없는 함수...
그리고 끝까지 떠났다.
float * ( *(* foo())[SIZE][SIZE])()
foo는 인수가 없는 함수로서 SIZE 포인터의 SIZE 포인터 배열로 포인터를 반환하고 인수가 없는 함수에 포인터를 플로트로 반환한다.
그리고 그 글을 쓴 사람이 누구였든 간에, 그에게 사용법을 가르쳐 주시오.typedef
:
// Function that returns a pointer to float
typedef float* PFloatFunc ();
// Array of pointers to PFloatFunc functions
typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];
// Function that returns a pointer to a PFloatFuncArray2D
PFloatFuncArray2D* foo();
cdecl.org에 따르면
foo를 함수로 선언하여 포인터 배열 SIZE의 배열 SIZE에 포인터 복귀 기능을 함수로 선언.
손으로 해독하려면 루치안 그리고레가 준 나선형 규칙을 사용한다.
여기서 가장 좋은 것은 일련의 타이핑으로 변환하는 것이다.
typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();
일반적으로 cdecl.org을 사용해 볼 수 있지만 대신SIZE
교환한다고 말함SIZE
12시간 동안 다음과 같은 혜택을 누리십시오.
foo를 함수로 선언하여 포인터 12 배열 12의 포인터로 포인터 복귀 기능 12 포인터
그게 너에게 정말 도움이 될지 모르겠어!
여기서 두 가지 관측치:
- 나는 이 코드가 그것의 목적이 무엇인지를 설명하는 코멘트는 옆에 없었으리라 추측한다(즉, 그것이 무엇에 대한 기술적 설명이 아니라 기능적/사업적 관점에서 그것이 달성하고 있는 것) 만약 프로그래머가 이와 같이 복잡한 것을 사용해야 한다면, 그들은 미래의 유지자들에게 어떤 목적을 설명하는데 충분해야 한다.서브를 넣다
- 확실히 C++에는 같은 것을 성취하는 더 분명하고 아마도 더 안전한 방법이 있을 것이다.
이 문서는 내게 C 선언문을 쉽게 준비하는 방법에 대한 가장 좋은 단서를 제공해준다.
http://c-faq.com/decl/spiral.anderson.html
따라야 할 세 가지 간단한 단계가 있다.
알 수 없는 요소부터 시작하여 나선형/시계 방향으로 이동하십시오. 다음 요소를 제거하면 해당 영문 문장으로 대체하십시오.
[X]
또는[]
=> 배열 X의 크기...또는 배열 정의되지 않은 크기...
(type1, type2)
=> 함수 전달 유형1 및 유형2 반환...
*
=> ...에 대한 포인터.모든 토큰이 커버될 때까지 나선형/시계 방향으로 계속 진행하십시오.
항상 괄호 안에 있는 모든 것을 먼저 해결하십시오!
예:
+-------+
| +-+ |
| ^ | |
char *str[10];
^ ^ | |
| +---+ |
+-----------+
Question we ask ourselves: What is str?
``str is an...
- We move in a spiral clockwise direction starting with `str' and the first character we see is a `[' so, that means we have an array, so...
``str is an array 10 of...
- Continue in a spiral clockwise direction, and the next thing we encounter is the `*' so, that means we have pointers, so...
``str is an array 10 of pointers to...
- Continue in a spiral direction and we see the end of the line (the `;'), so keep going and we get to the type `char', so...
``str is an array 10 of pointers to char''
We have now ``visited'' every token; therefore we are done!
foo를 함수로 선언하여 포인터 배열 SIZE의 배열 SIZE에 포인터 복귀 기능을 함수로 선언.
참조URL: https://stackoverflow.com/questions/15111526/complex-c-declaration
'IT이야기' 카테고리의 다른 글
Ubuntu 아래에 JDK 11을 설치하는 방법? (0) | 2022.04.25 |
---|---|
Java에서 임시 디렉토리/폴더를 만드는 방법? (0) | 2022.04.25 |
다른 엔드 Vue, JS인 경우 실행 기능 (0) | 2022.04.25 |
확인란 및 드래그 드롭이 있는 트리 구현 (0) | 2022.04.25 |
구성 요소 내부에 카운트업 애니메이션을 추가하는 방법 (0) | 2022.04.25 |