int ary[5];
100 104 108 112 116
-> [ int | int | int | int | int ]
배열은 첫 번째 요소의 주소만 알면 나머지 요소의 주소도 모두 알 수가 있다.
컴파일러는 첫 번째 배열 요소의 주소를 쉽게 사용하도록 배열명을 컴파일 과정에서 첫 번째 배열 요소의 주소로 변경한다.
즉, ary == 100
배열명으로 배열 요소 사용하기
[더하기]
ary배열의 첫 번째 값은 ary로 쓸 수 있지만 나머지 배열 요소들은 접근할 수 없다.
따라서 연산을 통해서 나머지 요소에 접근해보자.
ary + 1 // 104
위의 값이 101이 아니라 104가 나온 이유는 1은 주소 값에 +1을 해주는 것이 아니라 ary의 자료형의 1바이트 만큼의 수를 더해주는 것이다.
따라서 1은 sizeof(int) * 1과 같다.
ary + 3 // 100 + (3 * sizeof(int)) == 112 == ary[3]
이제 해당 방법과 간접 참조 연산자를 이용해서 값을 저장해보자.
#include <stdio.h>
int main(){
int ary[3];
*ary = 10; // == ary[0] = 10;
*(ary+1) = 20; // == ary[1] = 20;
*(ary+2) = *ary + *(ary+1); // ary[2] = 30;
for(int i = 0; i<(sizeof(ary)/sizeof(int)); i++){
printf("%d ", ary[i]);
}
return 0;
}
//10 20 30
포인터 변수를 이용해서 다시 값을 저장해보자.
#include <stdio.h>
int main(){
int ary[3];
int p = ary;
*(p+0) = 10; // == ary[0] = 10;
*(p+1) = 20; // == ary[1] = 20;
*(p+2) = *p + *(p+1); // ary[2] = 30;
for(int i = 0; i<(sizeof(ary)/sizeof(int)); i++){
printf("%d ", ary[i]);
}
return 0;
}
//10 20 30
[빼기]
#include <stdio.h>
int main(){
int ary[5] = {1, 2, 3, 4, 5};
// 100 104 108 112 116
//-> [ int | int | int | int | int ]
int *p = ary + 3; //112
int *q;
q = p - 3; //112 - (3 * 4) == 100
printf("%d", *q); // 1
return 0;
}
배열명과 포인터의 차이
1. sizeof 연산 결과가 다르다
int ary[3];
int *p = ary;
sizeof(ary); // 12, 배열 전체의 크기
sizeof(p); // 4, 포인터 변수 하나의 크기
2. 변수와 상수의 차이가 있다.
포인터는 그 값을 바꿀 수 있지만, 배열명은 상수이므로 값을 바꿀 수 없다.
pa = pa + 1 //가능
pa++ //가능
ary = ary + 1 //불가능
ary++ //불가능
2번 응용
#include <stdio.h>
int main(){
int ary[3] = {1, 2, 3};
int i = 0;
int *p = ary;
printf("배열은 ");
for (i = 0; i < 3; i++) {
printf("%d ", *(p++));
}
return 0;
}
//배열은 1 2 3
후위형은 다음 연산자인 간접 참조 연산을 수행할 떄는 증가되기 이전 값을 사용한다.
따라서 컴파일러는 p가 증가되기 이전 값을 임시 공간에 저장해 두었다가 간접 참조 연산에 사용하거나 연산자 우선순위를 바꾸어 p++보다 *p의 연산을 먼저 수행하도록 한다.
'문법관련 > C' 카테고리의 다른 글
11-2. 버퍼를 이용하는 입력 함수 (0) | 2024.06.25 |
---|---|
11-1. 아스키코드 (0) | 2024.06.25 |
9. 포인터 (0) | 2024.06.18 |
8. 함수 (0) | 2024.06.14 |
7. 반복문 - do while (0) | 2024.06.13 |