포인터 5부작 중 3부에요. 지난 2개의 글을 읽었거나, 이미 알고계신게 아니라면 이 시리즈의 지난 글들도 읽어주세요 😉
포인터를 배우고 나서 돌아보면, 배열 이름은 어떻게 동작하는지 궁금해져요. 여러 개의 원소를 가지고 있는데, 어떻게 이 원소들의 값을 가져오고 변경할 수 있는걸까요?
사실, 배열 이름은 배열의 첫 번째 원소를 가리키는 상수 포인터에요.
int array[3] = {1, 2, 3}, *p;
p = array; // p = &array[0];
printf("array[2] = %d\n", *(array + 2));
printf("*(p + 1) = %d\n", p[1]);
*(array + 2)
처럼, 포인터 연산을 사용할 수 있어요. 이는 array[2]
와 같아요.
반대로, 포인터 변수 p도 배열처럼 인덱스를 사용할 수 있어요.
p[1]
은 *(p + 1)
과 같아요.
하지만, 배열 이름은 상수 포인터라 기존 포인터와는 조금 달라요. 배열 이름은 배열의 첫 번째 원소를 가리키는 고정된 포인터라, 다른 주소를 가리킬 수 없어요.
int a[3] = {1, 2, 3};
int i = 4;
// 배열 이름의 주소는 변경할 수 없어요.
a = &i;
a++;
a = a + 1;
2차원 배열의 경우도 똑같이 다룰 수 있어요.
2차원 배열에서 인덱스 하나를 제거하면 포인터가 돼요.
int two[2][2] = {1, 2, 3, 4};
int *p = two[1]; // int *p = &two[1][0]
// two[1][1] == *(two[1] + 1)
printf("two[1][1] = %d\n", *(two[1] + 1));
2차원 배열에서 인덱스를 두 개 제거하면, 배열 포인터가 돼요.
int b[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int (*p)[3] = b; // p는 int[3]을 가리키는 포인터 변수에요.
printf("b[0][1] = %d\n", *( *b + 1 ) );
printf("b[1][0] = %d\n", *( *( p + 1) ) );
printf("b[2][2] = %d\n", *( *( p + 2 ) + 2) );
배열 이름이 포인터라는 건, 함수의 인자로 배열을 받을 때도 포인터로 받는다는 뜻이에요.
아래의 sum
함수는 배열 s와 배열의 크기 size를 받아, 배열 내 원소들의 합을 반환해요.
int sum(int s[], int size)
{
int sum = 0, i;
for (i = 0; i < size; i++)
sum += s[i];
return sum;
}
배열 s는 포인터로도 받을 수 있어요.
int sum_p(int *s, int size)
{
int sum, i;
for (i = 0; i < size; i++)
sum += *(s + i);
return sum;
}
배열을 매개 변수로 받는 함수를 호출 할 때, 주소 값을 전달하면 돼요.
int a[5] = {1, 2, 3, 4, 5}, i = 6, total;
total = sum(a, 5);
// total = a[0] + a[1] + ... + a[4]
total = sum(&a[2], 3);
// total = a[2] + a[3] + a[4]
total = sum(&i, 1);
// total = i
문자열도 문자의 배열이기 때문에, 앞선 예제들처럼 포인터로 다룰 수 있어요.
char *p = "abcde";
char s[] = "abcde";
printf("%c %c %c %c\n", p[0], *p, s[0], *s);
// a a a a
printf("%s %s\n", p, s);
// abcde abcde
printf("%s %s\n", p+2, s+2);
// cde cde
문자 배열과 문자열 포인터는 한가지 차이점을 가져요.
char name[20] = {};
char *name_p;
scanf("%s", name);
scanf("%s", name_p); // 오류
name은 이미 배열의 0번째 주소 값을 가지고 있는 상수 포인터라 scanf에 배열 이름을 넘겨주면 표준 입력으로부터 값을 받을 수 있어요.
하지만, name_p는 char형의 포인터일 뿐 아직 가리키는 주소가 없어서 scanf에 인자로 넘겨줘도 표준 입력에서 값을 받을 수 없어요.
배운 내용들을 정리해보고 있어요. 잘못 기재된 내용이 있다면, 댓글로 지적해주시면 수정할게요.