programing

포인터 배열에 대한 C 포인터 명확화

copysource 2022. 8. 10. 21:14
반응형

포인터 배열에 대한 C 포인터 명확화

다음 선언의 차이점은 무엇입니까?

int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);

보다 복잡한 선언을 이해하기 위한 일반적인 규칙은 무엇입니까?

int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers

세 번째 것도 첫 번째 거랑 똑같아요.

일반적인 규칙은 연산자 우선 순위입니다.기능 포인터가 등장함에 따라 훨씬 더 복잡해질 수 있습니다.

K&R의 제안에 따라 cdecl 프로그램을 사용합니다.

$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>

반대 방향으로도 작동합니다.

cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )

정식 명칭이 있는지는 모르겠지만, 저는 이것을 오른쪽-왼쪽의 싱키(TM)라고 부릅니다.

변수에서 시작해서 오른쪽, 왼쪽, 오른쪽...기타 등등.

int* arr1[8];

arr1는 정수에 대한8개의 포인터로 이루어진 배열입니다.

int (*arr2)[8];

arr2는 8개의 정수로 이루어진 배열에 대한 포인터(오른쪽과 왼쪽을 괄호로 둘러싸는 블록)입니다.

int *(arr3[8]);

arr3는 정수에 대한8개의 포인터로 이루어진 배열입니다.

이것은 복잡한 선언에 도움이 될 것입니다.

int *a[4]; // Array of 4 pointers to int

int (*a)[4]; //a is a pointer to an integer array of size 4

int (*a[8])[5]; //a is an array of pointers to integer array of size 5 

마지막 두 개의 답은 C의 황금 규칙에서도 차감할 수 있다.

사용 후에 선언합니다.

int (*arr2)[8];

를 해제하면 ?arr2여덟 살

int *(arr3[8]);

만약 당신이 그 요소들을 가져간다면 어떻게 될까요?arr3정수에 대한 포인터가 표시됩니다.

이것은 함수에 대한 포인터를 다룰 때도 도움이 됩니다.sigjuice의 예를 들자면:

float *(*x)(void )

?x인수 없이 호출할 수 있는 함수가 있습니다.화를를 걸떻 ?? ???됩니다.float.

그러나 연산자 우선 순위는 항상 까다롭습니다.다만, 선언 후에 사용되기 때문에 괄호를 사용하는 것도 실제로는 혼란스러울 수 있습니다.적어도 직감적으로 말하면arr2ints에 대한 8개의 포인터 배열처럼 보이지만 실제로는 그 반대입니다.이러한 선언에 코멘트를 할 수 있는 라고 하는 , 이러한를 추가할 수 .

편집: 예

그런데 우연히 다음과 같은 상황을 발견했습니다. 정적 매트릭스를 가지고 있고, 포인터 산술로 행 포인터가 경계를 벗어났는지 확인하는 함수입니다.예제:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))

int *
put_off(const int newrow[2])
{
    static int mymatrix[3][2];
    static int (*rowp)[2] = mymatrix;
    int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);

    memcpy(rowp, newrow, sizeof(*rowp));
    rowp += 1;
    if (rowp == border) {
        rowp = mymatrix;
    }

    return *rowp;
}

int
main(int argc, char *argv[])
{
    int i = 0;
    int row[2] = {0, 1};
    int *rout;

    for (i = 0; i &lt; 6; i++) {
        row[0] = i;
        row[1] += i;
        rout = put_off(row);
        printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
    }

    return 0;
}

출력:

0 (0x804a02c): [0, 0]
1 (0x804a034): [0, 0]
2 (0x804a024): [0, 1]
3 (0x804a02c): [1, 2]
4 (0x804a034): [2, 4]
5 (0x804a024): [3, 7]

경계 값은 변경되지 않으므로 컴파일러는 경계 값을 최적화할 수 있습니다. 것과 수 .const int (*border)[3]: 변수가 존재하는 한 값이 변경되지 않는 3개의 정수 배열에 대한 포인터로 경계를 선언합니다.단, 이 포인터는 언제든지 다른 배열을 가리킬 수 있습니다.대신 인수에는 그러한 동작이 필요합니다(이 함수는 이러한 정수를 변경하지 않기 때문입니다).사용 후에 선언합니다.

(p.s. 이 샘플을 자유롭게 개선하십시오!)

여기 C에서 복잡한 타입을 읽는 방법을 설명하는 흥미로운 웹사이트가 있습니다.http://www.unixwiz.net/techtips/reading-cdecl.html

경험으로 볼 때 오른쪽 단항 연산자(예:[],(), 등) 왼쪽보다 우선합니다.그렇게,int *(*ptr)()[];포인터 배열을 int로 반환하는 함수를 가리키는 포인터입니다(가능한 한 빨리 괄호에서 나오는 대로 올바른 연산자를 가져옵니다).

나는 우리가 간단한 규칙을 사용할 수 있다고 생각한다.

example int * (*ptr)()[];
start from ptr 

"ptr"오른쪽을 향해.." "왼쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" "오른쪽을 향해" 정수 "왼쪽을 향해" "왼쪽을 향해" "왼쪽을 반환" "" "오른쪽으로"

해석은 다음과 같습니다.

int *something[n];

우선순위에 관한 주의: 어레이 서브스크립트 연산자([])의 priority가 dereference 연산자(*).

여기에서는, 다음의 항목을 적용합니다.[]전에*이 명령어는 다음 명령어에 해당합니다.

int *(something[i]);

선언이 어떻게 의미가 있는지에 대해 주의해 주십시오.int num평균은 입니다.int *ptr ★★★★★★★★★★★★★★★★★」int (*ptr) (값: 균, 、 ) 。ptr)는 )입니다int①이 됩니다.ptrint.

이는 (물건의 ih 인덱스의 값)이 정수이기 때문에 읽을 수 있습니다.따라서 (무엇의 ith 인덱스의 값)은 (정수 포인터)이며, 이는 어떤 것을 정수 포인터의 배열로 만듭니다.

두 번째는

int (*something)[n];

이 문장을 이해하려면 다음 사실을 숙지해야 합니다.

에 관한 :somethingElse[i] *(somethingElse + i)

래래를 해서 환 so so so so so so 。somethingElse(*something) , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , .*(*something + i)선언에 따른 정수입니다.so,는,(*something)(배열과) 동등한 것을 만들 수 있는 배열이 있습니다.

정수에 대한 포인터에서 포인터가 증가하면 다음 정수로 이동합니다.

포인터 배열에서 포인터가 증가하면 다음 배열로 점프합니다.

typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];

나는 두 번째 선언이 많은 사람들에게 혼란스럽다고 생각한다.여기 그것을 이해하는 쉬운 방법이 있다.

정수를 요? 즉, 정수를 .int B[8].

B 리 A로 하다A 은 입 a a a a a a a a a(*A) == B따라서 A는 정수의 배열을 가리킵니다.A로 하다

마마에서는,int* (*C) [8]C는 정수에 대한 포인터 배열에 대한 포인터입니다.

int *arr1[5]

선언에서는, 「」를 참조해 주세요.arr1는 정수에 대한5개의 포인터로 이루어진 배열입니다.이유: 대괄호는 *(참조 해제 연산자)보다 우선도가 높습니다.이 유형에서는 행 수가 고정되지만(여기서는 5), 열 수는 가변적입니다.

int (*arr2)[5]

선언에서는, 「」를 참조해 주세요.arr2는 5개의 요소로 이루어진 정수 배열에 대한 포인터입니다.() 는 []보다높은 를 가집니다.여기서 () 괄호는 []보다 높은 우선순위를 가집니다.이 유형에서는 행 수가 가변적이지만 열 수는 고정되어 있습니다(여기에는 5개).

언급URL : https://stackoverflow.com/questions/859634/c-pointer-to-array-array-of-pointers-disambiguation

반응형