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 + 1
의 double
.
이 관용구는 자연스럽게 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 할당 방식과 완전히 동일하며 변경된 것은 다음 유형의 데이터뿐입니다.p
T *
은 , , , , , , , , , , , , , , , , , , , , , , .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
에 도달하고, 이 결론으로 대체하다, 라고 하면 됩니다.R
int [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
이 관용어에는 다음과 같은 이점이 있습니다.
- 단 한 돼요. 나누면 .
T **arr = malloc( sizeof *arr * N ); if ( arr ) { for ( size_t i = 0; i < N; i++ ) { arr[i] = malloc( sizeof *arr[i] * M ); } }
- 할당된 어레이의 모든 행은 *continuous*이며, 이는 위의 단편적인 할당 방식과는 다릅니다.
- 해제는, 1개의 할 수 .
free
arr[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
'itsource' 카테고리의 다른 글
Java에서 개체 배열을 문자열 배열로 변환하는 방법 (0) | 2022.08.16 |
---|---|
Vue에서 구성 요소가 생성되었을 때 기능을 구현하는 방법은 무엇입니까? (0) | 2022.08.16 |
vuejs에서 제목 태그를 동적으로 바인딩 (0) | 2022.08.16 |
Vuex에 있는 다른 상점의 getter를 어떻게 부르죠? (0) | 2022.08.16 |
Vuejs 자 컴포넌트 입력과 함께 폼 제출 (0) | 2022.08.16 |