itsource

2차원 어레이를 할당하는 이상한 방법?

mycopycode 2022. 8. 16. 23:37
반응형

2차원 어레이를 할당하는 이상한 방법?

프로젝트에서 누군가 이 선을 긋고 있습니다.

double (*e)[n+1] = malloc((n+1) * sizeof(*e));

(n+1)*(n+1)의 2차원 배열을 만들 수 있습니다.

아마도, 지금까지 제가 물어본 그 누구도 이것이 정확히 어떤 역할을 하는지, 어디서 유래했는지, 왜 작동해야 하는지(소문에 의하면, 그렇긴 하지만, 저는 아직 구입하지 않았습니다) 말할 수 없었기 때문입니다.

제가 뭔가 명백한 것을 놓치고 있는 것 같습니다만, 위 줄에 대해 설명해 주시면 감사하겠습니다.왜냐하면 개인적으로, 나는 우리가 실제로 이해하는 것을 사용한다면 훨씬 더 기분이 좋을 것 같기 때문이다.

''e 、 열 、 of of of of of of の 배열 입니다.n + 1「」의 double.

에서 참조 를 사용하다e입니다.e아아,아,아,아,아,아,아,아,아,아,아,아,아,아,아.n + 1「」의 double

malloc은 단순히 인 "Call"을 합니다.e (위)을 됩니다. (위)를 구하다.n + 1를 에 malloc . alloc본본 of of of of of of of of of of of of of of of의 배열을 n + 1「」의 배열n + 1double.

이 관용구는 자연스럽게 1D 어레이 할당에서 제외됩니다.해 보겠습니다.T:

T *p = malloc( sizeof *p * N );

간단하죠?표현 *p은 ★★★★★★★★★★★★★T, (그래서)sizeof *p sizeof (T)N- 의 T이는 모든 유형에 해당됩니다.

이번에는, 제이대대대uteuteuteute now now로 바꿔볼까요T" " " "와 같은 됩니다.R [10] 우리의 가 됩니다

R (*p)[10] = malloc( sizeof *p * N);

여기서의 의미론은 1D 할당 방식과 완전히 동일하며 변경된 것은 다음 유형의 데이터뿐입니다.pT *은 , , , , , , , , , , , , , , , , , , , , , , .R (*)[10].표현*p은 ★★★★★★★★★★★★★T '유형'입니다.R [10], (그래서)sizeof *p sizeof (T)은 와와다다 which에 해당합니다.sizeof (R [10]) 공간을 해 놓고 N타타에 10「」의 요소 R

더 갈 수 . 를 들어, 더 멀리 갈 수 있다.R는, 그 자체가 타입입니다.int [5]대체하다R 우리는 ★★★★★★★★★★★★★★★★★.

int (*p)[10][5] = malloc( sizeof *p * N);

거래 - ★★★★★★★★★★★★★★★★★★」sizeof *p is is is is is와 sizeof (int [10][5])「」, 「」, 「」를 할 수 있을 N타타에 10타타에 5을 지정합니다.int

이것이 할당측입니다.접근측에서는 어떨까요?

때 주의해 주세요.[]첨자 연산은 포인터 산술의 관점에서 정의됩니다.a[i]되어 있습니다.*(a + i)1. 따라서 첨자 연산자는[] 암묵적으로 포인터를 폐기합니다.한다면p에 대한 포인터입니다.T포인트 투 포인트의 값에 액세스 하려면 , 유니리와의 참조를 명시적으로 실시해 주세요.*연산자:

T x = *p;

또는 를 사용하여[]첨자 연산자:

T x = p[0]; // identical to *p

따라서 만약p배열의 첫 번째 요소를 가리키면 포인터의 첨자를 사용하여 해당 배열의 모든 요소에 액세스할 수 있습니다.p:

T arr[N];
T *p = arr; // expression arr "decays" from type T [N] to T *
...
T x = p[i]; // access the i'th element of arr through pointer p

자, 그럼 다시 치환 작업을 하고T어레이 타입으로R [10]:

R arr[N][10];
R (*p)[10] = arr; // expression arr "decays" from type R [N][10] to R (*)[10]
...
R x = (*p)[i];

바로 눈에 띄는 차이점 중 하나는 명백한 역참조라는 것입니다.p첨자 연산자를 적용하기 전에.우리는 구독을 원하지 않습니다.p, 델은 무엇을 서브스크립트 하고 싶은가?p (이 경우 어레이)를 가리킵니다. arr[0]단항이래*첨자보다 우선순위가 낮다[] 괄호를 으로 그룹화해야 .p* 위에서 때 *p is is is is is와 p[0]할 수 있습니다.

R x = (p[0])[i];

아니면 그냥

R x = p[0][i];

「 」의 는,p어레이를 2D 어레이에 수 .p다음과 같이 합니다.

R x = p[i][j]; // access the i'th element of arr through pointer p;
               // each arr[i] is a 10-element array of R

에 도달하고, 이 결론으로 대체하다, 라고 하면 됩니다.Rint [5]:

int arr[N][10][5];
int (*p)[10][5]; // expression arr "decays" from type int [N][5][10] to int (*)[10][5]
...
int x = p[i][j][k];

동작은 다음과 같습니다.p의 어레이를 하고 있는 , 를 개입시켜 되어 메모리를 포인트 있는 경우.malloc

이 관용어에는 다음과 같은 이점이 있습니다.

  1. 단 한 돼요. 나누면 .
    T **arr = malloc( sizeof *arr * N );
    if ( arr )
    {
      for ( size_t i = 0; i < N; i++ )
      {
        arr[i] = malloc( sizeof *arr[i] * M );
      }
    }
    
  2. 할당된 어레이의 모든 행은 *continuous*이며, 이는 위의 단편적인 할당 방식과는 다릅니다.
  3. 해제는, 1개의 할 수 .freearr[i]전에 전에할당 해제를 할당 취소할 수 있arr..

경우에 따라서는 힙이 심하게 단편화되어 연속된 청크로 메모리를 할당할 수 없거나 각 행의 길이가 다른 "jagged" 어레이를 할당하려는 경우 등 단편적인 할당 방법이 선호될 수 있습니다.하지만 일반적으로, 이것이 더 나은 방법입니다.


1. 어레이는 포인터가 아닙니다.대신 필요에 따라 어레이 식이 포인터 식으로 변환됩니다.

이것은 2D 어레이를 동적으로 할당하는 일반적인 방법입니다.

  • e형식의배열에대한 배열 포인터입니다 유형 배열에 반환되는 배열이 포인터입니다.double [n+1].
  • sizeof(*e)따라서 한 따라서 1의 크기인뾰족한 타입을 제공한다의 크기의pointed-at 형식의 형식을 준다.double [n+1]array.어레이를 설정합니다.
  • 당신은 공간을 할당하다에 방을 할당하며n+1그러한 배열입니다.이러한 어레이.
  • 당신은 어레이포인터를 설정합니다는 배열 포인터를 세웠다.e배열의 이 배열의 첫번째 배열에서 지적합니다.이 어레이의 첫 번째 어레이를 가리킵니다.
  • 이것은 당신이를 통해를 사용합니다.e~하듯이로e[i][j]2D배열에 개별 항목에 액세스 하려면.2D배열의 개별수 있습니다 액세스할 항목에.

개인적으로 이 스타일은 훨씬 읽기 쉽다고 생각합니다.

double (*e)[n+1] = malloc( sizeof(double[n+1][n+1]) );

언급URL : https://stackoverflow.com/questions/36794202/freaky-way-of-allocating-two-dimensional-array

반응형