1편 2020/10/17 - [Programming/C] - C언어 포인터 기본(C언어 basic pointer)
2편 2020/10/17 - [Programming/C] - C언어 포인터 활용(C언어 use of pointer) feat. swap함수
1편에서 했던 포인터 타입들의 크기가 모두 동일한데 여러개의 포인터 타입이 존재하는 이유가 무엇인지 살펴보았다.
(포인터 타입의 크기는 32bit machine에서는 4byte, 64 bit machine에서는 8byte이다)
결론을 다시 말하자면, 온전한 데이터를 읽으려면 지정된 주소부터 몇 byte를
읽어야 하는지 알려주기 위해서 포인터 타입이 존재한다 했다.
1 2 3 | int b = 0xffffffff int *pointerB = &b; | cs |
위 코드를 그림으로 그려보면, pointerB를 통해 b에 있는 값을 읽기 위해서는
시작주소 &b(0x1500) 부터 4byte를 읽어야 온전한 b의 값을 읽을 수 있다.
아래 코드는 포인터타입의 특징을 확인할 수 있는 또 다른 코드다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | int main() { int a; short b; double c; int *intPointer = &a; short *shortPointer = &b; double *doublePointer = &c; printf("int type size : %d,\ short type size : %d,\ double type size : %d\n",\ sizeof(int), sizeof(short), sizeof(double)); printf("&a : %x, &b : %x, &c : %x \n", &a, &b, &c); printf("intPointer : %x, shortPointer : %x, doublePointer : %x\n",\ intPointer, shortPointer, doublePointer); printf("intPointer+1 : %x, shortPointer+1 : %x, doublePointer+1 : %x\n",\ intPointer + 1, shortPointer + 1, doublePointer + 1); printf("intPointer+2 : %x, shortPointer+2 : %x, doublePointer+2 : %x\n",\ intPointer + 2, shortPointer + 2, doublePointer + 2); return 0; } | cs |
위 코드를 실행한 결과 다음과 같이 출력된다.
그림으로 그려보면,
(int *) 타입의 포인터 pointerInt 는 *pointerInt로
가리키는 공간의 데이터를 읽어보면 시작주소로 부터 4byte를,
(short *) 타입의 포인터 pointerShort 는 *pointerShort로
가리키는 공간의 데이터를 읽어보면 시작주소로 부터 2byte를,
(double *) 타입의 포인터 pointerDouble는 *pointerDouble로
가리키는 공간의 데이터를 읽어보면 시작주소로 부터 8byte를
읽게 된다.
여기까지는 1편에서 다루었던 내용이며,
우리가 오늘 보려하는 부분은 각 타입의 포인터변수에 + @ 를 해주는 부분이다.
결과를 다시 정리해서 보자면
변수명 | 결과 | 비고 | |
(int *) 포인터 | intPointer | 0xe5cf1aa8 | base1 |
intPointer + 1 | 0xe5cf1aac | base1로부터 4가 증가했다 | |
intPointer + 2 | 0xe5cf1ab0 | base1로부터 8이 증가했다 | |
(short *) 포인터 | shortPointer | 0xe5cf1aa6 | base2 |
shortPointer + 1 | 0xe5cf1aa8 | base2로부터 2가 증가했다 | |
shortPointer + 2 | 0xe5cf1aaa | base2로부터 4가 증가했다 | |
(double *)포인터 | doublePointer | 0xe5cf1a98 | base3 |
doublePointer + 1 | 0xe5cf1aa0 | base3으로부터 8이 증가했다 | |
doublePointer + 2 | 0xe5cf1aa8 | base3으로부터 16이 증가했다 |
포인터변수와 + 연산을 진행하면,
자료형의 크기를 곱한 만큼 증가 한다.
만약 아래와 같은 코드가 있다면
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <stdio.h> int main() { short arr[3] = { 1, 2, 3}; short *pShort = arr; printf("arr[i] : %d, %d, %d \n", arr[0], arr[1], arr[2]); printf("*(pShort + i) : %d, %d, %d \n", *(pShort), *(pShort+1), *(pShort+2)); printf("pShort[i] : %d, %d, %d \n", pShort[0], pShort[1], pShort[2]); printf("*(arr + i) : %d, %d, %d \n", *(arr), *(arr+1), *(arr+2)); printf("arr : 0x%x, pShort : 0x%x, &arr[0] : 0x%x\n", arr, pShort, &arr[0]); return 0; } | cs |
다음 그림과 같이 된다.
여기서 알아야 할 포인트는
1. 배열의 이름도 포인터다. (단 포인터 변수가 아닌 값을 바꿀 수 없는 포인터 상수이다)
즉 arr[i] 로 이제까지 값을 참조했지만, *(arr + i) 로 똑같은 값을 출력할 수 있음.
(배열 이름은 첫 번째 index의 주소 값을 나타냄, 위 그림에서는 0x10, 코드12번째 줄)
(다만 포인터 상수이기에 arr의 값을 바꿀 수는 없음!)
2. 1차원 배열은 인덱스가 증가할 때마다 데이터 자료형 크기만큼 증가한다.
--> 우리가 포인터변수에 + 연산 한 것과 동일하게 증가한다.
--> 즉, 1차원 배열은 우리가 이제까지 배운 포인터와 동일하다.
short arr[3] 에서 arr은 (short *p) 타입 포인터며,
int arr[3] 에서 arr은 (int *p) 타입 포인터이다.
3. 포인터를 배열 이름처럼 사용할 수 있다. (위 코드 10, 11번째 줄 결과값은 동일하다)
4. 배열의 이름은 포인터처럼 사용할 수 있다.
즉, arr[i] == *(arr + i) 이다. (코드 11번째 줄)
'Programming > C' 카테고리의 다른 글
구조체 비트 필드 structure bit field (0) | 2020.11.02 |
---|---|
정수 승격(integer promotion), 묵시적 형변환 (0) | 2020.10.21 |
C언어 포인터 활용(C언어 use of pointer) feat. swap함수 (0) | 2020.10.17 |
C언어 포인터 기본(C언어 basic pointer) (0) | 2020.10.17 |
가변길이 구조체(flexible array member) (0) | 2020.10.15 |