포인터의 크기, 선언 방법, 값과 주소 연산자
C언어를 공부할 때 스트레스를 받는 부분이 문자열을 만들고자 할 때부터 나오는 포인터를 이해하는 것이죠.
지금은 거의 다 64비트 컴퓨터를 사용 중이겠지만 대부분 책에는 32비트 프로그램으로 설명하니 저도 32비트로 설명합니다.
비주얼 스튜디오의 Windows 데스크톱 마법사로 콘솔 응용 프로그램을 만들면 기본적으로 32비트 프로그램을 만드는 환경으로 되어있습니다.
아래 빨간 줄 부분이 x86이면 32비트, x64이면 64비트 프로그램이 됩니다.
포인터의 크기
포인터의 크기는 32비트 프로그램이라면 4바이트입니다. sizeof() 함수로 확인할 수 있습니다.
포인터 변수는 가상 메모리의 주소를 가지고 있을 뿐이기에 32비트(= 4바이트) 주소 체계에선 주소의 길이인 4바이트의 크기를 가지는 것입니다.
#include <stdio.h> int main(void) { printf("%d\n", sizeof(char)); // 1 printf("%d\n", sizeof(int)); // 4 printf("%d\n", sizeof(float)); // 4 printf("%d\n", sizeof(double)); // 8 printf("%d\n", sizeof(char*)); // 4 printf("%d\n", sizeof(int*)); // 4 printf("%d\n", sizeof(float*)); // 4 printf("%d\n", sizeof(double*));// 4 }
포인터의 선언 방법
포인터 선언 방법은 데이터 타입, *(간접 지정 연산자), 변수 이름을 순서대로 쓰기만 하면 됩니다. 다음 코드는 모두 정상입니다.
int* count; int *count; int*count; int * count;
- count라는 이름을 가진 변수는
- *가 붙었으니 포인터 변수이고
- int가 있으니 이 포인터가 가지고 있는 주소엔 정수가 있어야 한다. 라고 거꾸로 읽으면서 이해하면 쉽습니다.
주소 연산자
주소 연산자 &는 변수의 주소를 반환합니다. 따라서 다음처럼 포인터 변수를 선언과 동시에 초기화할 수 있습니다.
int num = 100; int *count = #
포인터 변수가 먼저 선언되었다면 다음처럼 초기화할 수 있습니다.
int num = 100; int *count; count = #
만약 포인터 변수에 주소가 아닌 값을 넣으면 참조 수준이 다르다는 오류가 납니다. 예를 들어
count = num;
이렇게 주소가 아닌 정수를 넣는다면 말이죠. 데이터 타입이 다르면 변수의 크기가 4바이트로 동일해도 오류입니다.
하지만 정수를 포인터로 캐스팅(형 변환)하는 것은 가능합니다.
//int형 포인터의 경우 int num = 100; int *count; count = (int*)num; // char형 포인터의 경우 int num=100; char *count; count = (char*)num;
int형 포인터라면 (int*)로 char형 포인터라면 (char*)로 말이죠.
하지만 이 경우 포인터가 메모리 주소 100을 가리키게 됩니다. 이렇게 쓸 일은 없습니다. 이걸 읽기라도 했다간 프로그램은 비정상 종료됩니다. 궁금하시다면 printf()로 *count 값을 출력해보세요.
포인터의 값
이번엔 1. 포인터 변수의 주소와 2. 포인터 변수가 가지고 있는 값과 3. 포인터 변수가 가리키고 있는 값을 출력해봅시다.
int num=100; int *count; count = # printf("%d\n", &count); //9697236 printf("%d\n", count); //9697248 printf("%d\n", *count); //100 printf("%d\n", &num); //9697248 printf("%d\n", num); //100
간단하게 하려고 형식 지정자를 %d로 통일했고 출력 결과는 주석에 쓰여있습니다.
출력 결과는 각자 다를 수 있습니다. 중요한 건
- count라는 포인터 변수가 있는 곳은 967236이고
- 이 곳에(포인터 변수가 가지고 있는 값이) 9697248이란 값이 들어있고
- 이 값은 주소로 num이라는 변수가 있는 곳이며
- 이 곳엔(num 변수가 가지고 있는 값이) 100이란 값이 있다는 것입니다.
count 포인터 변수는 num 변수가 있는 곳을 가리키고 있으므로
*count = 200; printf("%d\n", *count); // 200 printf("%d\n", num); // 200
이렇게 간접 지정 연산(*)으로 값을 변경할 수 있습니다.
제가 c언어 공부하면서 궁금한 게 생겨서 여쭤볼려고 합니다.
만약에 2차원 배열에 16진수 형태로 초기값을 넣고, char 포인트 변수로 배열의 값이랑 바이트를 어떻게 구할 수 있을까요?
값이 하나일때는 출력되는데 두개 이상부터는 안되네요ㅠ
char arr[2][3] = { {1,3,5},{7,9,11} };
printf(“%d\n”, *(*(arr))); // 1
printf(“%d\n”, *(*(arr)+1)); // 3
printf(“%d\n”, *(*(arr)+2)); // 5
printf(“%d\n”, *(*(arr+1))); // 7
printf(“%d\n”, *(*(arr+1)+1)); // 9
printf(“%d\n”, *(*(arr+1)+2)); // 11
char *p = *(arr+1)+2; // 11이 있는 주소
*p = *p + 10;
printf(“%d\n”, *p); // 21
이런걸 말씀하시는 거죠?