데이터의 주소값이란 해당 데이터가 저장된 메모리의 시작 주소를 의미한다. 그리고 C언어에서는 이러한 주소값을 1바이트 크기의 메모리 공간으로 나누어 표현한다. 여기서 알아야할 점은 int형 데이터는 4바이트의 크기를 가지지만 int형 데이터의 주소값은 시작 주소 1바이트만을 가리킨다는 것이다.
그리고 C언어에서 포인터란 메모리의 주소값을 저장하는 변수이며, 포인터 변수라고도 부른다. 즉, char형 변수가 문자를 저장하고, int형 변수가 정수를 저장하는 것처럼 포인터는 주소값을 저장한다.
int n = 100; // 변수 선언
int *ptr = &n; // 포인터 선언
C언어에서 포인터와 연관되어 사용되는 연산자는 주소 연산자(&), 참조 연산자(*)가 있다.
주소 연산자(&)는 변수의 이름 앞에 사용하며 해당 변수의 주소값을 반환한다. & 기호를 사용하며 ampersand라고 읽으며, 번지 연산자라고 불린다.
참조 연산자(*)는 포인터의 이름이나 주소 앞에 사용하며, 포인터가 가리키는 주소에 저장된 값을 반환한다. 다만 C 언에서 * 기호는 사용하는 위치에 따라 다양한 용도로 사용되는 것에 주의할 필요가 있다. 즉, 이항 연산자로 사용하면 곱셉 연산으로 사용되며, 포인터의 선언시나 메모리에 접근할 때도 사용된다.
C언에서 포인터는 다음 문법에 따라 선언한다. 이때, 타입은 포인터가 가리키고자 하는 변수의 타입을 명시한다. 그리고 포인터 이름은 포인터가 선언된 후에 포인터에 접근하기 위해 사용된다. 포인터를 선언한 후 참조 연산자를 사용하기 전에 포인터는 반드시 먼저 초기화되어야 한다. 그렇지 않으면 의도하지 않은 메모리의 값을 변경하게 되기 때문이다. 따라서 C 컴파일러는 초기화하지 않은 포인터에 참조 연산자를 사용하면 오류를 발생시킨다. 즉, 포인터의 선언과 동시에 초기화를 함께 하는 것이 좋다는 얘기이다.
타입* 포인터이름 = &변수이름;
또는
타입* 포인터이름 = 주소값;
C언어에서 선언된 포인터는 참조 연산자(*)를 사용하여 참조할 수 있다. 즉, 다음과 같이 포인터의 주소값과 함께 포인터가 가리키고 있는 주소값의 데이터를 참조할 수 있다.
int x = 7; // 변수 선언
int *ptr = &x; // 포인터 선언
int *pptr = &ptr; // 포인터 참조
또한 다음과 같이 포인터가 가리키는 변수의 타입에 따라 포인터의 타입도 같이 바꿔줄 수 있는데, 이렇게 하는 이유는 포인터의 타입은 참조 연산자를 통해 값을 참조할 때, 참조할 메모리의 크리를 알려주는 역할을 하기 때문이다.
int num01 = 1234;
double num02 = 3.14;
int* ptr_num01 = &num01;
double* ptr_num02 = &num02;
① printf("포인터의 크기는 %d입니다.\n", sizeof(ptr_num01));
② printf("포인터 ptr_num01이 가리키고 있는 주소값은 %#x입니다.\n", ptr_num01);
③ printf("포인터 ptr_num02가 가리키고 있는 주소값은 %#x입니다.\n", ptr_num02);
printf("포인터 ptr_num01이 가리키고 있는 주소에 저장된 값은 %d입니다.\n", *ptr_num01);
printf("포인터 ptr_num02가 가리키고 있는 주소에 저장된 값은 %f입니다.\n", *ptr_num02);
포인터의 크기는 8입니다.
포인터 ptr_num01이 가리키고 있는 주소값은 0x7c255e4입니다.
포인터 ptr_num02가 가리키고 있는 주소값은 0x7c255e8입니다.
포인터 ptr_num01이 가리키고 있는 주소에 저장된 값은 1234입니다.
포인터 ptr_num02가 가리키고 있는 주소에 저장된 값은 3.140000입니다.
다음은 char형 포인터와 int형 포인터가 각각 메모리 상에서 해당 타입의 변수를 가리키는 그림인데, 타입에 따라 달라지는 참조할 메모리의 크기를 확인할 수 있다.
그리고 포인터 변수 또한 메모리에서 변수의 위치를 나타내는 주소를 다루는 변수이므로 일반적으로 CPU에 따라 그 크기가 결정되는데, 32비트 CPU에서는 1워드의 크기가 4바이트이므로 포인터 변수의 크기 또한 4바이트가 될 것이다. 다만 이러한 포인터 변수의 크기는 컴파일러로 컴파일할 때 그 크기까지 직접 명시할 수 있다. 따라서 포인터 변수의 크기는 CPU의 종류와 컴파일할 때 사용된 컴파일러의 정책에 따라서 달라질 수 있다.
워드(word)란 CPU가 한 번에 처리할 수 있는 데이터의 크기다. 1바이트는 8비트이므로 32비트 시스템에서는 32비트 / 8비트 = 4, 즉 4바이트가 1워드(word)로 처리된다. 64비트 시스템에서는 64비트 / 8비트 = 8, 즉 8바이트가 1워드(word)로 처리된다.
인용
https://www.tcpschool.com/c/c_pointer_intro
코딩교육 티씨피스쿨
4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등
tcpschool.com
'Language > C' 카테고리의 다른 글
구조체 (0) | 2023.11.05 |
---|---|
키워드 _CRT_SEUCRE_NO_WARNINGS에 대하여 (0) | 2023.11.05 |
typedef, enum, union (0) | 2023.11.05 |
컴파일과 디버깅 (0) | 2023.11.02 |
헤더 파일 (0) | 2023.09.28 |