C 다차원 배열의 포인터 주소
저는 다차원 배열과 포인터를 만지작거리고 있습니다.저는 간단한 배열의 내용과 주소를 출력하는 프로그램을 보고 있었습니다.제 어레이 선언문은 다음과 같습니다.
int zippo[4][2] = { {2,4},
{6,8},
{1,3},
{5,7} };
이해하는 로는,zippo
는 포인터이며 다른 포인터 몇 개의 주소를 저장할 수 있습니다.으로,zippo
합니다의 합니다.zippo[0]
의 주소인 도 할 수 있습니다.zippo[1]
,zippo[2]
,그리고.zippo[3]
.
자, 다음과 같은 말을 들어보겠습니다.
printf("zippo[0] = %p\n", zippo[0]);
printf(" *zippo = %p\n", *zippo);
printf(" zippo = %p\n", zippo);
내 컴퓨터에서 다음과 같은 출력이 나옵니다.
zippo[0] = 0x7fff170e2230
*zippo = 0x7fff170e2230
zippo = 0x7fff170e2230
합니다의 이유를 합니다.zippo[0]
그리고.*zippo
같은 가치를 가지다 둘다 둘다 2 둘 다 포인터이며 기본값 2 의 주소(를 저장합니다) 둘 다 정수의 를 합니다.zippo[0][0]
왜 그래요? 요?zippo
또한 같은 메모리 주소를 공유하고 있습니까? 돼요zippo
다의 .zippo[0]
뭐라고요?
배열 표현식이 대부분의 컨텍스트에서 나타날 때, 그 유형은 "T의 N-element array"에서 "T로의 포인터"로 암묵적으로 변환되고, 그 값은 배열의 첫 번째 요소를 가리키도록 설정됩니다.의 피연산자인 입니다.sizeof
의 &
연산자 또는 배열이 선언에서 이니셜라이저로 사용되는 문자열 리터럴인 경우.
ㅇzippo
int [4][2]
어레이) ~ (열의 열 에서int (*)[2]
(인트의 2-element 배열에 포인터).마찬가지로, 다음과 같은 유형의zippo[0]
이다.int [2]
암묵적으로 됩니다.int *
.
,int zippo[4][2]
및 즉, 는 zippo .
식 유형이 해당 식으로 암묵적으로 변환됨---------- ---- ----------------------- ---------------------지퍼[4][2] int(*)[2]&zipoint(*)[4][2]*지포[2] int * 지포[0]zippo[i] int [2] int *&zipo[i] int(*)[2]*zippo[i] intzippo[i][0]지포[i][j]int&zippo[i][j] int **zippo[i][j] 유효하지 않음
:zippo
,&zippo
,*zippo
,zippo[0]
,&zippo[0]
,그리고.&zippo[0][0]
모두 동일한 값을 갖습니다. 모두 배열의 맨 아래 부분을 가리킵니다(배열의 주소는 배열의 첫 번째 요소의 주소와 동일합니다).하지만 다양한 표현의 종류는 모두 다릅니다.
다차원 배열을 선언하면 컴파일러는 이 배열을 단일 차원 배열로 취급합니다.다차원 배열은 우리의 삶을 더 쉽게 만들기 위한 추상적인 것에 불과합니다.오해하고 있습니다.이것은 4개의 어레이를 가리키는 하나의 어레이가 아니라, 항상 하나의 연속적인 메모리 블록일 뿐입니다.
당신의 경우 다음을 수행합니다.
int zippo[4][2]
하는 것과 정말 같습니다.
int zippo[8]
컴파일러가 2D 어드레싱에 필요한 연산을 처리합니다.
자세한 내용은 C++의 배열에 대한 이 자습서를 참조하십시오.
이는 다음과 크게 다릅니다.
int** zippo
아니면
int* zippo[4]
이 경우에는 다른 배열에 할당할 수 있는 4개의 포인터의 배열을 만드는 것입니다.
zippo
는 포인터가 아닙니다.배열 값의 배열입니다.zippo
,그리고.zippo[i]
위해서i
값에서) 수 있습니다. 04에서는 특정한 경우(특히 값 컨텍스트에서) 포인터로 "decay"할 수 있습니다.ysizeof zippo
를 들어,를 예로 zippo
비가치적인 맥락에서이 경우에는.sizeof
는 포인터의 크기가 아닌 배열의 크기를 보고합니다.
값 컨텍스트에서 배열의 이름은 첫 번째 요소의 포인터로 표시됩니다.그래서, 가치적 맥락에서,zippo
.&zippo[0]
의 " " [2] 에 포인터" .int
";*zippo
는 , 와 .&zippo[0][0]
"에 대한 , , "에 포인터.int
는 같지만." 그들은 가치는 같지만 종류는 다릅니다.
두 번째 질문에 답하려면 배열 및 포인터를 읽는 것이 좋습니다.포인터의 "값"은 같지만 공간의 양은 다릅니다.인쇄 시도zippo+1
그리고.*zippo+1
그것을 더 명확하게 볼 수 있습니다.
#include <stdio.h>
int main(void)
{
int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5,7} };
printf("%lu\n", (unsigned long) (sizeof zippo));
printf("%p\n", (void *)(zippo+1));
printf("%p\n", (void *)(*zippo+1));
return 0;
}
내가 도망칠 때는 다음과 같이 출력합니다.
32
0xbffede7c
0xbffede78
을 해주니깐.sizeof(int)
내 기계에서 4이고 두번째와 세번째 포인터의 값이 같지 않습니다(예상대로).
."%p"
svoid *
인에*printf()
당신은 당신의 들,다에 .void *
n에printf()
printf()
는 가변 함수이므로 컴파일러가 자동 변환을 수행할 수 없습니다.
편집: 배열이 포인터에 "흔들어진다"고 말하면 값 컨텍스트에서 배열의 이름이 포인터와 동일하다는 의미입니다.따라서, 만약 내가T pt[100];
타입의 T
에 이름, ㅇpt
입니다.T *
가치적인 맥락에서 말입니다.sizeof
d&
자,자pt
포인터로 축소되지 않습니다.하지만 당신은 할 수 있습니다.T *p = pt;
는 이러한 , 합니다이기 pt
입니다.T *
.
이 "쇠락"은 한 번만 일어난다는 것에 유의하세요.자, 예를 들면 다음과 같습니다.
int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5,7} };
그리고나서,zippo
in value context의 는 유형의 포인터로 붕괴합니다.열[2]합니다.int
코드명:
int (*p1)[2] = zippo;
유효한 반면에
int **p2 = zippo;
incomp 호환 포인터 할당" 경고를 트리거합니다.
와 함께zippo
되며,
int (*p0)[4][2] = &zippo;
int (*p1)[2] = zippo;
int *p2 = zippo[0];
모두 유효합니다.다를 할 때 .printf("%p\n", (void *)name);
포인터들은 정수를 에서 다릅니다 , .
은 그 입니다.int zippy[4][2]
다와(와) 다른 입니다.int **zippo
.
처럼.int zippi[5]
,zippy
메모리 블록의 주소입니다.그러나 컴파일러는 당신이 8개의 메모리 위치를 다루기를 원한다는 것을 알고 있습니다.zippy
으로 .나 5다.zippi
일차원적인 구문으로
zippo
완전히 다른 것입니다.두 개의 포인터를 포함할 수 있을 정도로 충분히 큰 메모리 블록의 주소를 보유하고 있으며 정수의 일부 배열을 가리키게 할 경우 2차원 배열 액세스 구문을 사용하여 참조를 해제할 수 있습니다.
잘해 주었는데, , 할 때 좀 더 .zippo
아니면zippo[0]
아니면zippo[0][0]
한 기본 주소인 를 .zippo
는 여러 어레이가 항상 연속된 메모리 블록이고 다차원 어레이가 연속적으로 배치되는 이유는 여러 단일 차원 어레이입니다.
할에는 포인터 int *p = &zippo[0][0]
, ㅇp++
포인터가 행 단위로 증가합니다.에서 id는 4 X 2이고,4 X 2 배열입니다.p++
의 두 번째 재 4다를 있습니다
언급URL : https://stackoverflow.com/questions/2003745/pointer-address-in-a-c-multidimensional-array
'programing' 카테고리의 다른 글
Android studio 오류 "지원되지 않는 모듈이 탐지됨:다음 모듈에 대해서는 컴파일이 지원되지 않습니다." (0) | 2023.10.04 |
---|---|
메모리 내 데이터베이스 디스크에 저장 (0) | 2023.10.04 |
연산자를 매개변수로 전달 (0) | 2023.10.04 |
스키마를 잃었습니다.rb!재생할 수 있습니까? (0) | 2023.10.04 |
MySql - InnoDB를 MyISAM Storage Engine of Database로 변환 (0) | 2023.10.04 |