본문으로 바로가기

   

 

배열의 이름은 포인터이다.
단, 그 값을 바꿀 수 없는 '상수 형태의 포인터'이다.

#include <stdio.h>

void main()
{
	int arr[3] = { 0,1,2 };
	printf("배열의 이름 %p\n", arr);	// 배열의 이름 == 첫 번째 변수 //배열의 이름 006FFEB0
	printf("첫 번째 요소 : %p\n", &arr[0]); // 배열의 이름과 같은 주소값을 띈다. //첫 번째 요소 : 006FFEB0
	printf("두 번째 요소 : %p\n", &arr[1]); // 두 번째 요소 : 006FFEB4
	printf("세 번째 요소 : %p\n", &arr[2]); // 세 번째 요소 : 006FFEB8
	//arr = &arr[i]; // 이 문장은 컴파일 에러를 일으킨다. >>>> 상수여서 불가능하다.
}

배열의 이름은 배열의 시작 주소 값을 의미하며, 그 형태는 저장이 불가능한 상수이다.

1차원 배열이름의 포인터 형과 배열이름을 대상으로 하는 *연산
1차원 배열이름의 포인터 형은 배열의 이름이 가리키는 대상을 기준으로 결정하면 된다.

#include <stdio.h>
void main()
{
	int arr1[3] = { 1,2,3 };
	double arr2[3] = { 1.1,2.2,3.3 };

	printf("%d \t %lf\n", *arr1, *arr2);	// 1	1.1
	*arr1 += 100;
	*arr2 += 120.5;
	printf("%d \t %lf\n", arr1[0], arr2[0]); // 101		121.6
}

 

포인터 연산
int형 포인터를 대상으로 n x sizeof(int)의 크기만큼 증가 
double형 포인터를 대상으로 n x sizeof(double)의 크기만큼 증가
.
.
감소의 결과도 이와 같은 방식이며 감소한다.
TYPE형 포인터를 대상으로 n의 크기만큼 값을 증가 및 감소 시, n x sizeof(TYPE)의 크기만큼 주소 값이 증가 및 감소한다.

★중요한 결론

printf("%d %d %d\n", *(ptr + 0), *(ptr + 1), *(ptr + 2)); // *(ptr+0) == *ptr
printf("%d %d %d\n", ptr[0], ptr[1], ptr[2]);
printf("%d %d %d\n", *(arr + 0), *(arr + 1), *(arr + 2)); // *(arr+0) == *arr
printf("%d %d %d\n", arr[0], arr[1], arr[2]);

 

 

네 문장 모두 동일한 결과 값을 출력한다.
arr[i] == *(arr+i) //arr[i]는 *(arr+i)와 같다.

 

상수 형태의 문자열을 가리키는 포인터
char str1[ ] = "My String" // 배열의 길이는 자동으로 계산 // 변수 형태의 문자열
char* str2[] = "Your String" // 상수라 문자 변경 불가능. // 상수 형태의 문자열

#include <stdio.h>
void main()
{
	char str1[] = "My String"; // 변수 형태의 문자열
	char* str2 = "Your String"; // 상수 형태의 문자열 // 상수이기 때문에 배열[]을 안씀!
	printf("%s %s\n", str1, str2);

	str2 = "Our String";
	printf("%s %s\n", str1, str2);
	str1[0] = 'x';	//문자열 변경 성공
	str2[0] = 'x';	//문자열 변경 실패(에러발생)
	printf("%s %s\n", str1, str2);
}

 

 

포인터 배열
포인터 변수로 이뤄진 배열
int* arr1[20]; // 길이가 20인 int형 포인터 배열 arr1
double* arr2[30]; // 길이가 30인 double형 포인터 배열 arr2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <stdio.h>

void main()
{
	int num1 = 10, num2 = 20, num3 = 30;
	int* arr[3] = { &num1, &num2, &num3 };

	printf("%d\n", *arr[0]);	//10
	printf("%d\n", *arr[1]);	//20
	printf("%d\n", *arr[2]);	//30
}

 

이렇듯 포인터 배열도 기본 자료형 배열과 별반 다르지 않다. 

변수의 자료형을 표시하는 위치에 int나 double 대신 *int와 *double이 올 뿐이다.

 


문제1)
길이가 5인 int형 배열 arr을 선언하고 이를 1,2,3,4,5로 초기화 한 다음, 이 배열의 첫 번째 요소를 가리키는 포인터 변수 ptr을 선언한다. 그 다음 포인터 변수 ptr에 저장된 값을 증가시키는 형태의 연산을 기반으로 배열 요소에 접근하면서 모든 배열요소의 값을 2씩 증가시키고, 정상적으로 증가가 이뤄졌는지 확인하는 예제를 작성해보자.

#include <stdio.h>
void main()
{
	int arr[5] = { 1,2,3,4,5 };
	int * ptr = &arr[0]; // &arr[0] = arr // 배열의 첫 번째 변수 == 배열의 이름
	int i;
	for (i = 0; i < 5; i++)
	{
		*ptr += 2;
		ptr++;
		printf("arr[%d] : %d\n", i, arr[i]);
	}
}

 

 

문제2)
문제1에서는 포인터 변수 ptr에 저장된 값을 변경시켜가면서 배열요소에 접근하라고 하였다.
그런데 이번에는 포인터 변수 ptr에 저장된 값을 변경시키지 않고, ptr을 대상으로 덧셈연산을 하여, 그 결과로 반환되는 주소 값을 통해서 모든 배열요소에 접근하여 값을 2씩 증가시키는 예제를 작성해보자.

#include <stdio.h>
void main()
{
	int arr[5] = { 1,2,3,4,5 };
	int * ptr = &arr[0];
	int i;

	for(i=0; i<5; i++)
	*(ptr + i) += 2;

	for (i = 0; i < 5; i++)
	printf("arr[%d] : %d\n", i, arr[i]);
}

 

 

문제3)
길이가 5인 int형 배열 arr을 선언하고 이를 1,2,3,4,5로 초기화한 다음, 이 배열의 마지막 요소를 가리키는 포인터 변수 ptr을 선언한다. 그 다음 포인터 변수 ptr에 저장된 값을 감소시키는 형태의 연산을 기반으로 모든 배열요소에 접근하여, 배열에 저장된 모든 정수를 더하여 그 결과를 출력하는 프로그램을 작성해보자.

#include <stdio.h>
void main()
{
	int arr[5] = { 1,2,3,4,5 };
	int * ptr = &arr[4];
	int i;
	int total = 0;

	for (i = 4; i >= 0; i--) {
		total += *ptr--;
		printf("arr[%d] : %d\n", i, arr[i]);
	}
	printf("%d\n", total);

}