code

C의 2D 배열 포인터

starcafe 2023. 6. 12. 21:38
반응형

C의 2D 배열 포인터

좋은 (그리고 효과적인) 해결책을 제공하는 것에 대해 몇 가지 질문이 있다는 것을 알지만, 이를 달성하기 위한 최선의 방법이 무엇인지 명확하게 말해주는 IMHO는 없습니다.2D 어레이가 있다고 가정해 보겠습니다.

int tab1[100][280];

우리는 이 2D 배열을 가리키는 포인터를 만들고 싶습니다.이를 위해 다음을 수행할 수 있습니다.

int (*pointer)[280]; // pointer creation
pointer = tab1; //assignation
pointer[5][12] = 517; // use
int myint = pointer[5][12]; // use

또는 다음과 같은 기능을 사용할 수 있습니다.

int (*pointer)[100][280]; // pointer creation
pointer = &tab1; //assignation
(*pointer)[5][12] = 517; // use
int myint = (*pointer)[5][12]; // use 

좋아요, 둘 다 잘 되는 것 같아요.이제 저는 알고 싶습니다.

  • 제일 좋은 방법은 무엇입니까, 1번입니까, 2번입니까?
  • 컴파일러의 경우 둘 다 같습니까? (속도, 성능...)
  • 이 해결책들 중 하나가 다른 해결책보다 더 많은 메모리를 먹는 것입니까?
  • 개발자들이 더 자주 사용하는 것은 무엇입니까?
//defines an array of 280 pointers (1120 or 2240 bytes)
int  *pointer1 [280];

//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280];      //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers

용사를 합니다.pointer2또는pointer3을 제외하고는 합니다.++pointer2WhozCraig가 지적한 바와 같이.

를 사용하는 것이 좋습니다.typedef 코드 (binary 생성)pointer3)

typedef int myType[100][280];
myType *pointer3;

참고: C++11부터는 키워드도 사용할 수 있습니다.usingtypedef

using myType = int[100][280];
myType *pointer3;

예:

myType *pointer;                // pointer creation
pointer = &tab1;                // assignation
(*pointer)[5][12] = 517;        // set (write)
int myint = (*pointer)[5][12];  // get (read)

참고: 배열의 경우tab1는 함수 본체 내에서 사용됩니다 => 이 배열은 콜 스택 메모리 내에 배치됩니다.그러나 스택 크기는 제한되어 있습니다.사용 가능한 메모리 스택보다 큰 어레이를 사용하면 스택 오버플로 충돌이 발생합니다.

전체 스니펫은 gcc.godbolt.org 에서 온라인으로 컴파일할 수 있습니다.

int main()
{
    //defines an array of 280 pointers (1120 or 2240 bytes)
    int  *pointer1 [280];
    static_assert( sizeof(pointer1) == 2240, "" );

    //defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
    int (*pointer2)[280];      //pointer to an array of 280 integers
    int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers  
    static_assert( sizeof(pointer2) == 8, "" );
    static_assert( sizeof(pointer3) == 8, "" );

    // Use 'typedef' (or 'using' if you use a modern C++ compiler)
    typedef int myType[100][280];
    //using myType = int[100][280];

    int tab1[100][280];

    myType *pointer;                // pointer creation
    pointer = &tab1;                // assignation
    (*pointer)[5][12] = 517;        // set (write)
    int myint = (*pointer)[5][12];  // get (read)

    return myint;
}

두 예제 모두 동일합니다.하지만, 첫 번째 것은 덜 명백하고 더 "해킹"한 반면, 두 번째 것은 당신의 의도를 분명히 말합니다.

int (*pointer)[280];
pointer = tab1;

pointer280개의 정수로 구성된 1D 배열을 가리킵니다.당신의 과제에서, 당신은 실제로 첫 번째 행을 할당합니다.tab1이것은 배열을 포인터(첫 번째 요소)에 암시적으로 캐스팅할 수 있기 때문에 작동합니다.

를 때.pointer[5][12]는 C를 처리합니다.pointer어레이 배열로서(pointer[5]이 형의입니다.int[280]), 따라서 여기에는 (적어도 의미론적으로) 또 다른 암묵적인 캐스팅이 있습니다.

두 번째 예에서는 2D 배열에 대한 포인터를 명시적으로 만듭니다.

int (*pointer)[100][280];
pointer = &tab1;

은 여기서 더 합니다: 의론은여더명확다니합서기에.*pointer이므로 2D 어레이를 사용하여 .(*pointer)[i][j].

두 솔루션 모두 동일한 양의 메모리(포인터 1개)를 사용하며 동일한 속도로 실행될 가능성이 높습니다.에서, 두 포인터는 같은 .tab1배열), 그리고 당신의 컴파일러가 같은 코드를 생성할 가능성도 있습니다.

첫 번째 솔루션은 현재 진행 중인 상황을 이해하기 위해 C에서 어레이와 포인터가 작동하는 방식에 대해 상당히 깊은 이해가 필요하기 때문에 "더 발전된" 솔루션입니다.두 번째는 좀 더 명확합니다.

int *pointer[280];//int 유형의 포인터 280개를 만듭니다.

32비트 os에서는 포인터당 4바이트입니다.따라서 4 * 280 = 1120 바이트입니다.

int (*pointer)[100][280];[100][280] int의 배열을 가리키는 데 사용되는 포인터를 하나만 만듭니다.

여기서는 4바이트만 사용합니다.

질문을 드리자면,int (*pointer)[280];그리고.int (*pointer)[100][280];동일한 [100][280]의 2D 어레이를 가리키지만 다릅니다.

왜냐하면 만약에int (*pointer)[280];증가하면 다음 1D 어레이를 가리킵니다. 하지만,int (*pointer)[100][280];전체 2D 배열을 교차하고 다음 바이트를 가리킵니다.해당 메모리가 프로세스에 속하지 않는 경우 해당 바이트에 액세스하면 문제가 발생할 수 있습니다.

자, 이것은 사실 네 가지 다른 질문입니다.제가 그들을 하나씩.

둘 다 컴파일러와 같습니까?(속도, 성능...)

네, 포인터의 참조가 빗나가서 유형에서 사라졌습니다.int (*)[100][280]로.int (*)[280]CPU에 항상 문제가 됩니다.나는 어쨌든 가짜 코드를 생성하기 위해 나쁜 컴파일러를 지나치지는 않겠지만, 좋은 최적화 컴파일러는 두 예제를 정확히 같은 코드로 컴파일해야 합니다.

이 해결책들 중 하나가 다른 해결책보다 더 많은 메모리를 먹는 것입니까?

제 첫 번째 대답의 결과로, 아니오.

개발자들이 더 자주 사용하는 것은 무엇입니까?

확실히 추가 사항이 없는 변종입니다.(*pointer)불심검문C 프로그래머의 경우 포인터가 실제로 배열의 첫 번째 요소에 대한 포인터일 수 있다고 가정하는 것은 제2의 천성입니다.

제일 좋은 방법은 무엇입니까, 1번입니까, 2번입니까?

이는 무엇을 위해 최적화하느냐에 따라 달라집니다.

  • 관용 코드는 변형 1을 사용합니다.선언문에 외부 차원이 누락되었지만 모든 용도는 C 프로그래머가 예상하는 대로입니다.

  • 배열을 가리키고 있음을 명시적으로 표시하려면 변형 2를 사용할 수 있습니다.하지만 많은 숙련된 C 프로그래머들은 가장 안쪽 뒤에 숨겨진 3차원이 있다고 생각할 것입니다.*배열 차원이 없다는 것은 대부분의 프로그래머들에게 이상하게 느껴질 것입니다.

언급URL : https://stackoverflow.com/questions/14808908/pointer-to-2d-arrays-in-c

반응형