IT이야기

복합 C 선언

cyworld 2022. 4. 25. 21:51
반응형

복합 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};

tabx로 포인망으로 을 할 수 있다.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] 기기는 '차르'

우선순위 및 연관성

다음으로 우리는 의 우선 순위를 알아야 한다.()[]그리고*- 참조 해제 연산자

  1. ()[]- 연관성은 왼쪽에서 오른쪽으로
  2. *- 연관성은 오른쪽에서 왼쪽으로

위의 각 연산자에 해당하는 구문

다음으로 각 연산자에 해당하는 디코딩된 구문을 알아야 한다.앞의 예들을 보면 이 점을 분명히 알 수 있을 것이다.

  • () 가능
  • [SIZE] SIZE 배열의
  • *- 에 대한 포인터

이제 선언문을 해독하려면 아래의 규칙을 따르십시오.

  1. 항상 변수 이름 다음에 'is'를 쓰십시오.

    예를 들어 -

  • int a- a는 …이다.
  • float *p- p는...
  • char (*p)[3]- p는...
  1. 항상 기본 유형으로 끝내기

    예를 들어 -

  • int a- a는 …이다.인트로
  • float *p- p는...둥둥 뜨다
  • char (*p)[3]- p는...마를 뜨다
  1. 이제 다음 하위 단계를 사용하여 중간 부분을 채우십시오.

    • 이름에서 시작하여 연산자 우선 순위 및 연관성을 따라 차상위 연산자를 선택하고 이에 해당하는 구문을 디코딩된 문자열의 중간 부분에 추가한다.

    • 디코딩 프로세스가 완료될 때까지 나머지 선언에 대해 위의 하위 단계를 반복하십시오.

비고 1: 단순성을 위해 함수의 인수는 무시했지만, 함수의 인수는 다음과 같은 구문 바로 뒤에 포함될 수 있다.().

참고 2: 괄호()() 연산자의 우선순위를 다른 산술식처럼 변경한다.

비고 3: 해독된 선언에서 괄호를 사용하여 가독성을 높일 수 있다(아래 몇 가지 예에서 나는 그것을 했다).()의 각 세트를 하나의 단위로 생각하라.

참고 4: n차원 배열은 실제로 ... (n-1회) 배열의 배열이다.ex - int A[2][3] - A는 2의 배열이다(3 int의 배열). 즉, A는 각 요소가 3개의 정수를 포함하는 배열인 2개의 원소의 배열이다.

  • int a- a는 int
  • float *p- p는 플로트에 대한 포인터임
  • char (*p)[3]- p는 3자 배열의 포인터임

몇 가지 복잡한 선언 사례

  1. int **p[10]- p는 포인터에서 int에 이르는 10개의 포인터 배열이다.
  2. int (*p)[10]- p는 10 int 배열에 대한 포인터임
  3. int *p(char *a)- p는 포인터를 int로 되돌리는 기능이다.
  4. int (*p(char*a))[10]10p는 기고(10 int)로 한다.
  5. int *(*p)() 복귀(p는 (기)의 대인(int)에 대한 다.
  6. int (*p()[20])[10] p는 는(배열 20 (10 int))이다.

이 규칙 집합은 다음에서 사용할 수 있다.const또한 - const 한정자는 용어를 왼쪽(있는 경우)으로 수정한다. 그렇지 않으면 오른쪽(있는 경우)으로 수정한다.

  1. const int *p[10]- p는 int const에 대한 10개의 포인터 배열이다.
  2. int const *p[10]- p는 const에 대한 10개의 포인터 배열이다(7번째 예와 동일).
  3. int *const p[10]한 것이다.

이제 실제로 그 용도를 어디서도 찾을 수 없지만 그럼에도 불구하고 디코딩 과정을 증명하는 데 사용될 수 있는 정말 복잡한 예시

  1. 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

교환한다고 말함SIZE12시간 동안 다음과 같은 혜택을 누리십시오.

foo를 함수로 선언하여 포인터 12 배열 12의 포인터로 포인터 복귀 기능 12 포인터

그게 너에게 정말 도움이 될지 모르겠어!

여기서 두 가지 관측치:

  1. 나는 이 코드가 그것의 목적이 무엇인지를 설명하는 코멘트는 옆에 없었으리라 추측한다(즉, 그것이 무엇에 대한 기술적 설명이 아니라 기능적/사업적 관점에서 그것이 달성하고 있는 것) 만약 프로그래머가 이와 같이 복잡한 것을 사용해야 한다면, 그들은 미래의 유지자들에게 어떤 목적을 설명하는데 충분해야 한다.서브를 넣다
  2. 확실히 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!

http://cdecl.org/에서

foo를 함수로 선언하여 포인터 배열 SIZE의 배열 SIZE에 포인터 복귀 기능을 함수로 선언.

참조URL: https://stackoverflow.com/questions/15111526/complex-c-declaration

반응형