배열의 이름도 포인터이다. 단, 그 값을 바꿀수 없는 '상수형태의 포인터'이다.
예제1)
#include <stdio.h>
int main()
{
int arr[3] = { 0,1,2 };
printf("배열의 이름 : %p \n", arr);
printf("첫번째요소 %p \n", &arr[0]);
printf("두번째요소 %p \n", &arr[1]);
printf("세번째요소 %p \n", &arr[2]);
//arr=&arr[i]; 이문장은 컴파일 에러를 일으킨다.
return 0;
}
%p:주소값을 출력하기 위한 서식문자
실행결과
실행결과를 총해 알수 있는 것
: int형 배열 요소간의 주소값의 차는 4바이트 이다.
arr의 메모리 공간 할당 형태
결론
:배열의 이름은 배열의 시작 주소 값을 의미하며,그 형태는 값의 저장이 불가능한 상수이다.
배열의 이름==포인터 상수
포인터이기 때문에 배열의 이름을 피 연산자로 하는 * 연산도 가능하다.
#include <stdio.h>
int main()
{
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;
}
결과
printf("%d %g \n", *arr1, *arr2);
arr1과 arr2가 가리키는 대상을 출력하고 있다. 따라서 arr1과 arr2가 가리키는 배열의 첫번째 요소가 출력된다.
#include <stdio.h>
int main()
{
int arr1[3] = { 1,2,3 };
arr1[0] += 5;
arr1[1] += 7;
arr1[2] += 9;
....
}
위의 코드에서 배열이름 arr은 int형 포인터이니, 포인터 대상으로 배열의 모든 요소를 arr[0],arr[1],arr[2]로 접근했다.
포인터 변수 ptr대상으로 ptr[0],ptr[1],ptr[2]와 같은 형태로 메모리 공간에 접근이 가능하다.
#include <stdio.h>
int main()
{
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;
}
위예제에서 보듯이 포인터 변수를 배열의 이름처럼 사용하는 경우는 거의 없고 마찬가지로 배열의 이름을 포인터 변수처럼 사용하는 경우도 거의 없다. 하지만 이런 일이 가능하다는 사실은 알고 있어야한다. 포인터를 정확히 이해하는데 중요한 지식이다.
포인터 변수를 대상으로 다음과 같이 다양한 형태의 증가 및 감소 연산을 진행할 수 있다.
#include <stdio.h>
int main()
{
int* ptr1 = 0x0010;
double* ptr2 = 0x0010;
printf("%p %p\n", ptr1 + 1, ptr1 + 2); //4가 증가하고 8이 증가한다.
printf("%p %p\n", ptr2 + 1, ptr2 + 2); //8이 증가하고 16이 증가한다
printf("%p %p\n", ptr1, ptr2);
ptr1++;
ptr2++;
printf("%p %p\n", ptr1, ptr2);
return 0;
}
이런 연산 특성으로 인해 다음예제에서 보이는 배열 접근이 가능하다.
#include <stdio.h>
int main()
{
int arr[3] = { 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;
}
(++ptr)=20; //ptr에 저장된 값 자체를 변경
(ptr+1)=20; //ptr에 저장된 값은 변경하지 않음
중요한 결론! arr[i]==*(arr+i)
나중에 배울 다차원 배열에도 유용한 식이니 꼭 기억해야 한다!
내가 쓴답(정산 출력됨) 이게 2번 정답..!
#include <stdio.h>
int main()
{
int arr[5] = { 1,2,3,4,5};
int* ptr = arr;
int len = sizeof(arr) / sizeof(int);
for (int i = 0; i < len; i++)
{
*(ptr + i) += 2;
}
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
정답
#include <stdio.h>
int main()
{
int arr[5] = { 1,2,3,4,5};
int* ptr = arr;
int len = sizeof(arr) / sizeof(int);
for (int i = 0; i < len; i++)
{
*ptr+=2;
ptr++;
}
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
#include <stdio.h>
int main()
{
int arr[5] = { 1,2,3,4,5};
int* ptr = arr;
int len = sizeof(arr) / sizeof(int);
for (int i = 0; i < len; i++)
{
*(ptr + i) += 2;
}
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
#include <stdio.h>
int main()
{
int arr[5] = {1,2,3,4,5 };
int* ptr = &arr[4]; //배열이름이 아니니까 &를 써줘야 주소로 인식된다
int i = 0;
int sum = 0;
for (i=0; i < 5; i++)
{
sum += *ptr;
ptr--;
}
printf("합:%d", sum);
return 0;
}
#include <stdio.h>
int main()
{
int arr[6] = { 1,2,3,4,5,6 };
int* start = arr;
int* fin = &arr[5];
int i, temp;
for (i = 0; i < 3; i++)
{
temp = *start;/포인터가 가리키는 값에 접근할때 :*ptr;
*start=*fin;
*fin = temp;
start++;
fin--;
}
for (i = 0; i < 6; i++)
printf("%d ",arr[i]);
return 0;
}
문자열의 선언방식
1.배열을 이용
2.char형 포인터 변수를 이용
1.변수 형태의 문자열
배열을 대상으로는 값의 변경이가능하다
char str1[]="my string"; //배열의 길이는 자동적으로 저장된다
2.상수형태의 문자열
char*str2="your string";
포인터 변수str2가 가리키는 문자열은 그 내용의 변경이 불가능하다.
이렇게 선언하면 메모리 공간에 문자열이 저장되고, 문자열의 첫번째 문자y의 주소값이 반환된다. 그리고 그 반환 값이 포인터 변수 str2에 저장된다.
두 문자열 선언의 차이점
"배열이름 str1은 계속해서 문자 m이 저장된 위치를 가리키는 상태이여야 하지만 포인터 변수 str2는 다른 위치를 가리킬 수 있다."
char *str="const string";
문장이 처리되는 과정
1 문자열이 메모리 공간에 저장
2.메모리값 주소값이 반환
문자열이 저장된 이후 아래와 같은 형태가 됨.
//과정1
char *str=0x1234; //0x1234번지에 저장되었다고 가정.
함수 호출과정에서 선언되는 문자열을 처리하는과정
마찬가지로 메모리 공간에 저장죈 후 그 주소값이 반환된다. 따라서 이 함수 호출 문장도 메모리 공간에 문자열이 저장된 이후 바로 과정1과 같은 형태가 된다.
printf("show your string");
printf함수는 문자열의 주소값을 전달받는 함수다!"
포인터 배열
:포인터 변수로 이루어져 주소값의 저장이 가능한 배열
int * arr1[20];
double * arr2[30];
예제
#include <stdio.h>
int main()
{
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형 포인터 배열
:문자열 주소값을 저장할수 있는 배열
char * strArr[3]; //길이가 3인 포인터 배열
예제
#include <stdio.h>
int main()
{
char* strArr[3] = { "simple","string","arrary" };
printf("%s\n", strArr[0]);
printf("%s\n", strArr[1]);
printf("%s\n", strArr[2]);
return 0;
}
큰따옴표로 묶어서 표시되는 문자열은 그 형태에 상관없이 메모리 공간에 저장된후 그 주소값이 반환된다