[Software]/Programming Tips2009. 3. 27. 11:19
설명 2개 참조

1. 출처 ( http://ani2life.egloos.com/2063818 )

포인터 배열과 배열의 포인터
오늘 포인터에 대해서 외우는 것이 아니라 제대로 이해를 하기 위해 공부했습니다.
가뜩이나 이해력 딸리는 머리라 뜻을 너무 힘들었습니다. 휴~

일단 CN님의 포인터 구구단에서 우선순위를 읽어봤습니다.

이제 머리를 괴롭혀 볼까요? ㅡㅡ;

int *p[2]; //포인터 배열
int (*p)[2]; //배열의 포인터

포인터 배열은 말그대로 int형 변수의 주소를 값으로 가질 수 있는 2개짜리 포인터 변수입니다.

p[0] = &n1;
p[1] = &n2;

이런식으로 사용합니다.

문제는 배열의 포인터 였습니다.
도대체 이게 무엇을 말하는 것인지 봐도봐도 이해가 안되더군요.
직접 코딩 테스트를 통해서 삽질을 해서 알았습니다.

배열크기가 [SIZE]인 변수를 참조할 수 있는 포인터 이더군요. ㅡㅡ;
저는 계속 (*p)가 2개라고 생각하고 있었습니다.

우선순위에 따라서 읽어보겠습니다.
"(*p)포인터인데 배열[2]짜리 int 형 변수를 가리킬 수 있는 변수"

그런데 문제가...

int n[2];
int (*p)[2];

p = n; //에러
p = &n[0]; //에러
p = &n; //정상

n = &n[0] = &n 이 모두 같은 값을 나타내는데 에러가 난다는 것은?
나름대로 이론을 잡아가고 있었는데 이 부분에서 팍 막혀버렸습니다.

처음에는 대충 생각없이 &n과 n의 값은 서로 다를거라고 생각했는데 출력해보니 같은 값;;

디버그를 내용은 아래와 같습니다.
cannot convert from 'int [2]' to 'int (*)[2]' //p = n;
cannot convert from 'int *' to 'int (*)[2]' //p = &n[0];

이런~ 즉, 이말은 변수형이 틀리다는 뜻인가? 패닉에 빠지기 시작합니다.

이렇게 되면 n = &n[0] = &n 가 값이 같다고해서 같다고 생각할 수 없군요.

아래와 같이 표현할 수 있겠습니다.
n[0] 은 int
&n[0] 은 int *
n 은 int []
&n 은 int (*)[]

그렇다면 지금까지 &는 해당변수의 주소값을 나타낸다 라고 생각했는데 단순히 그렇게 생각하면 안되겠습니다.
&는 해당변수의 주소값을 가지고 있는 임시의 포인터변수와 같이 되는 것이라고 해야하지 않을까요?


그럼 이제 좀더 괴로움에 떨어 볼까요? ㅡㅡ;

int n[2][2];
int (*p)[2];

p = n; //정상
p = &n[0]; //정상

&n[0]에서 n[0]는 n[0][0]를 가르키는 int [2]이고 여기에 &를 함으로써 int (*)[2]가 되었습니다.
그렇다면 n은... 머리가 복잡해지네요. ㅠㅠ

n은 n[0]를 가르키는데 n[0]는 int [2]이기에 int [2]를 가르킬 수 있는 n은 int (*)[2]형이어야 한다고 해석할 수 있겠습니다.

참고로 &n은 int (*)[2][2] 라고 나옵니다.
당연히 int[2][2]를 가르킬 수 있는 포인터 변수형은 int (*)[2][2] 일 수 밖에 없겠지요? (ㅡㅡ;)

마지막으로 배열의 포인터라 함은 배열을 가르킬 수 있는 포인터임이 확실하다 라고 말 할 수 있겠습니다.

역시 국내의 암기식 포인터 교육의 한계가 느껴지네요. ㅠㅠ

배열에 포인터가 이렇게 난무하니까 힘드시죠?
하지만 우리에겐 구조체와 클래스가 있습니다. 만세~! ^^




2. 출처 ( http://achiven.tistory.com/1175583213 )

배열과 포인터에대해 많이 헷갈렸었는데,

여기서 정리해보겠습니다.
(개념 3줄요약있음)

int (*array_p)[3]; ->배열포인터
int *array_p[3]; -> 포인터의 배열
의 차이입니다.

===============================================

int (*array_p)[3];
이렇게 선언한느것은 무엇을 뜻하는 것일까요.

이것은 이른바 '배열포인터'라고 하는 것입니다

포인터는 자신이 가리키는 어떤 타입(기본타입일수도 있고 구조체일수도 있습니다) 이 있습니다.
int *ptr; 이것은 ptr은 int형 변수를 가리킬거라는 이야기이고
CustomType *ptr; 이것은 ptr은 CustomType이라는 사용자가 정의한 타입의 변수를 가리킬거라는이야기 입니다.

그렇다면 저기 array_p는 포인터로 선언이 되었습니다.
그렇다면 무엇을 가리키는 것일까요.?

그것은 (int형3개짜리 배열)이라는 타입을 가진 변수를 가리킨다는 이야기입니다.

int array[3];
int (*array_p)[3];

이렇게 선언하고

array_p = &array; 라고 배열이 있는 곳의 주소값을 포인터에 넣을수 있습니다.

그렇다면
array_p = array 이것은 안되는 것일까요?
array 도 일종의 포인터로 해당 배열의 주소를 가지고 있고
&array도 주소값을 가지고 있습니다.

하지만  array는 int의 포인터일뿐이지  (int형3개짜리 배열)의 포인터는 아니기 때문에 컴파일러는 경고를 표시합니다
(물론 같은 주소를 가리키기는 합니다)


int의 포인터에 1을더하면 4바이트 나아가겠지만
(int형3개짜리 배열)의 포인터에 1을 더하면 12바이트가 나아갈겁니다.

============================================

그에비해
int *array_p[3]; 이렇게 선언한것은 무엇을 뜻할까요.?

예를 들어보겠습니다.

int var;
이것은 4바이트

int var[10];
이것은 int형 배열로 총 40바이트를 가집니다.

int *pVar[10];
이것은 (int의 포인터)의 배열, 요소수는 10개.. 즉 4바이트짜리 포인터가 10개 있으므로 40바이트입니다

double *pVar[10];
이것은 자칫 double이 8바이트짜리니까 총 80바이트 아니냐고 생각할지 모르겟지만
(double의 포인터)의 배열, 요소수는 10개 즉 포인터는 무엇을 가리키든 4바이트이므로.  40바이트가 됩낟.

그렇다면 즉
int *array_p[3];  이것은
array_p라는 포인터가 차례대로 3개가 있다는 이야기이고 용량은 4바이트곱하기 3개 하면 12바이트가 됩니다.

 

=========================================

포인터의 배열 사용례)

char *fruit[5]={"사과","배","고구마"};
이런것은 포인터의 배열입니다.

각각의 문자열은 메모리상에 임의의 번지에 저장 되구요.. 그것들의 시작주소가 포인터 변수에 들어갑니다.

즉 *fruit[0],*fruit[1],*fruit[2]... ... 이렇게 주소값을 저장하는 포인터 변수가 5개라는 것이죠..


배열포인터 사용례)

int (*a)[3];
이것은 [3]개의 int 값을 가지는 배열을 지시하는 포인터 변수가 한개입니다. 포인터가 여러개가 아닙니다  int가 3개짜리인 배열을 딱하나의 포인터변수가 가리킬따름입니다.

이것은 2차원 배열을 함수로 넘길때 많이 사용합니다.
int sum(int (*a)[3],int size);
이런식으로요.

array[2][5] 이렇게 있으면
이말은 5개의 크기를 가진 배열을 2개의 배열이 가리킨다는얘기죠,

array[2][5] ={"사과", "고구마"};
이것은 5는 각 글자의 최대 길이를 말하는것이고

여기서 "사과" 이 문자열자체가 배열이됩니다. 이 배열에서의 원소는 "사", "과", "/0"이 되겠죠. (\0인가..?-_-;;)
이런 배열이 2개가 있다는것이고

ㅁ -> ㅁㅁㅁㅁㅁ
ㅁ -> ㅁㅁㅁㅁㅁ

이런이야기 입니다.

그런데 이 2중배열을 함수로 넘길때는?

포인터로 넘겨야 되는것은 확실한데 무엇을 가리키는 포인터를 넘겨야 하는가..라고 했을때

char array[2][5] ={"사과", "고구마"};
이경우에는 char형 5개짜리 의 타입을 가리키는 포인터 를 넘기면 되겠죠?
그렇다면 이것은 함수인자로 넘길때
void myfunction(char (*array_p)[3], int size);

뭐 이런식으로 사용하면 될겁니다..

void myfunction(char array[][3], int size); 이런식으로 표기하기도 하지만요..

긴글읽어주셔서 감사합니다.
틀린점이 있음 지적해 주세요,


3줄요약
int (*array_p)[3]; ->배열포인터이고 (3개짜리 배열)을 가리키는 포인터 한개를 선언한것.
int *array_p[3]; -> 포인터의 배열이고 포인터가 차례대로 3개를 뜻하는것이다.
배열포인터는 이중배열을 함수값으로 넘길때 쓰이고 포인터의 배열은 여러개의 문자열들의 배열을 나타낼때 쓰인다


Posted by 바트정