배열의 이름은 값을 바꿀 수 없는 상수 형태의 포인터이다.
#include<stdio.h>
int main(void)
{
int arr[3] = {0,1,2};
printf("배열의 이름: %p \n", arr); //%p: 주소 값의 출력에 사용된다.
printf("첫 번째 요소: %p \n", &arr[0]);
printf("두 번째 요소: %p \n", &arr[1]);
printf("세 번째 요소: %p \n", &arr[2]);
//arr = &arr[i]; //이 문장은 컴파일 에러를 일으킨다.
return 0;
}
실행결과
배열의 이름: 0012FF50
첫 번째 요소: 0012FF50
두 번째 요소: 0012FF54
세 번째 요소: 0012FF58
배열의 이름과 포인터 변수 모두 이름이 존재하며, 특정 메모리 공간의 주소 값을 지닌다. 다만 포인터 변수는 변수지만, 배열의 이름은 가리키는 대상의 변경이 불가능한 상수라는 점에서 차이를 보인다. 즉 배열의 이름은 상수 형태의 포인터이다. 그래서 배열의 이름을 가리켜 포인터 상수라고 부르기도 한다.
1차원 배열이름의 포인터 형은 배열의 이름이 가리키는 대상을 기준으로 결정하면 된다.
int arr1[5];
배열 이름 arr1이 가리키는 것은 배열의 첫번째 요소인데, 그것은 int형 변수이므로 arr1은 int형 포인터이다.
double arr2[7];
배열 이름 arr2가 가리키는 것은 첫번째 배열요소인 double형 변수이므로 arr2는 double형 포인터가 된다.
#include <stdio.h>
int main(void)
{
int arr1[3] = {1, 2, 3};
double arr2[3] = {1.1, 2.2, 3.3};
printf("%d %g \n", *arr1, *arr2);
*arr1 += 100;
*arr2 += 120.5;
printf("%d %g \n", arr1[0], arr2[0]);
return 0;
}
실행결과
1 1.1
101 121.6
배열의 이름과 포인터 변수는 변수냐 상수냐의 특성적 차이가 있을 뿐, 둘 다 포인터이기 때문에 포인터 변수로 할 수 있는 연산은 배열의 이름으로도 할 수 있고, 그 반대도 가능하다.
#include <stdio.h>
int main(void)
{
int arr[3] = {15, 25, 35};
int* ptr = &arr[0]; //int* ptr = arr;과 동일한 문장
printf("%d %d \n", ptr[0], arr[0]);
printf("%d %d \n", ptr[1], arr[1]);
printf("%d %d \n", ptr[2], arr[2]);
printf("%d %d \n", *ptr, *arr);
return 0;
}
실행결과
15 15
25 25
35 35
15 15
int형 포인터를 대상으로 1을 증가시키면 4가 증가하고, double형 포인터를 대상으로 1을 증가시키면 8이 증가한다.
#include <stdio.h>
int main(void)
{
int* ptr1 = 0x0010;
double* ptr2 = 0x0010;
printf("%p %p \n", ptr1+1, ptr1+2);
printf("%p %p \n", ptr2+1, ptr2+2);
printf("%p %p \n", ptr1, ptr2);
ptr1++;
ptr2++;
printf("%p %p \n", ptr1, ptr2);
return 0;
}
실행결과
00000014 00000018
00000018 00000020
00000010 00000010
00000014 00000018
즉, 포인터를 대상으로 하는 증감연산의 결과는 다음과 같다.
n×sizeof(type) 의 크기만큼 주소 값이 증감
#include <stdio.h>
int main(void)
{
int arr[4] = { 11, 22, 33 };
int* ptr = arr;
printf("%d %d %d \n", *ptr, *(ptr + 1), *(ptr + 2));
printf("%d ", *ptr); ptr++;
printf("%d ", *ptr); ptr++;
printf("%d ", *ptr); ptr--;
printf("%d ", *ptr); ptr--;
printf("%d ", *ptr); printf("\n");
return 0;
}
실행결과
11 22 33
11 22 33 22 11
포인터 변수 ptr은 int형 포인터이므로 값을 1 증가시킬 때 실제로 4가 증가한다. 따라서 배열 arr이 할당된 위치의 주소 값을 0x001000이라 가정할 때, (ptr+1)과 (ptr+2)의 연산 결과로 반환되는 주소 값은 각각 0x001004, 0x001008이다. 결국 [*ptr], [*(ptr+1)], [*(ptr+2)]의 참조결과 출력 시 arr[0], arr[1], arr[2]에 저장된 요소가 출력된다.
#include <stdio.h>
int main(void)
{
int arr[5] = { 1, 2, 3, 4, 5 };
int* ptr = &arr[0];
printf("%d ", (*ptr) + 2);
printf("%d ", (*(++ptr)) + 2);
printf("%d ", (*(++ptr)) + 2);
printf("%d ", (*(++ptr)) + 2);
printf("%d ", (*(++ptr)) + 2);
printf("\n");
return 0;
}
#include <stdio.h>
int main(void)
{
int arr[5] = {1, 2, 3, 4, 5};
int* ptr = &arr[0];
printf("%d ", (*ptr) + 2);
printf("%d ", (*(ptr + 1)) + 2);
printf("%d ", (*(ptr + 2)) + 2);
printf("%d ", (*(ptr + 3)) + 2);
printf("%d ", (*(ptr + 4)) + 2);
printf("\n");
return 0;
}
#include <stdio.h>
int main(void) {
int arr[5] = { 1, 2, 3, 4, 5 };
int sum = 0;
int* ptr = &arr[4];
for (int i = 0; i < 5; i++) {
sum += (*(ptr--));
}
printf("%d \n", sum);
return 0;
}
#include <stdio.h>
int main(void)
{
int arr[6] = { 1,2,3,4,5,6 };
int* ptr1 = &arr[0];
int* ptr2 = &arr[5];
int temp = 0;
for (int i = 0; i < 3; i++)
{
temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
ptr1 += 1;
ptr2 -= 1;
}
for(int i=0; i<6; i++)
printf("%d ", arr[i]);
return 0;
}
char str1[] = "My String";
char* str2 = "Your String";
메모리 공간에 문자열 "Your String"이 저장되고, 문자열의 첫 번째 문자 Y의 주소값이 반환되어 포인터 변수 str2에 저장된다.
char* str = "Const String";
printf("Show your string");
""로 묶여서 표현되는 문자열은 그 형태에 상관없이 메모리 공간에 저장된 후 그 주소 값이 반환된다. 따라서 문자열이 0x1234번지에 저장되었다고 가정하면, 다음과 같은 형태가 된다.
printf(0x1234);
즉, printf 함수는 문자열의 주소 값을 전달받는 함수임을 알 수 있다.
WhoAreYou("Hong");
위와 같이 함수를 호출했을 때, 실제로 전달되는 값은 문자 H의 주소 값이므로 WhoAreYou 함수의 매개변수 선언은 다음과 같아야 한다.
void WhoAreYou(char* str){...}
주소 값을 저장할 수 있도록 포인터 변수를 대상으로 선언된 배열
#include <stdio.h>
int main(void)
{
int num1 = 10, num2 = 20, num3 = 30;
int* arr[3] = {&num1, &num2, &num3};
printf("%d \n", *arr[0]);
printf("%d \n", *arr[1]);
printf("%d \n", *arr[2]);
return 0;
}
문자열의 주소 값을 저장할 수 있는 배열로, 사실상 char형 포인터 배열
#include <stdio.h>
int main(void)
{
char* strArr[3] = {"Simple", "String", "Array"};
printf("%s \n", strArr[0]);
printf("%s \n", strArr[1]);
printf("%s \n", strArr[2]);
return 0;
}