-
C언어 개념 정리 (주소 연산자, 포인터 변수, 그리고 역참조 연산자)IT 자격증 공부/정보처리기사 2025. 3. 30. 16:08
1. 주소 연산자(&)
주소 연산자 &는 변수가 저장된 메모리의 위치(주소)를 알려줍니다.
간단한 비유로 설명하자면,
- 우리의 집이 변수라고 가정하면 -> 집 = 자세한 주소
- 우리의 집의 주소(예: 서울시 강남구 ...)가 메모리 주소라고 이해할 수 있습니다.
- 그런 의미에서 &는 "~의 주소는?"이라고 묻는 것과 같습니다.
int number = 10; printf("%p", &number); // number 변수의 메모리 주소를 출력 (예: 0x7ffeeb0dbc4c)
2. 포인터 변수(*)
포인터 변수는 직접 데이터를 저장하지 않고, 다른 변수의 위치(주소)를 가리키는 역할을 합니다.
💡 일반 변수와 포인터 변수의 차이점
- 일반 변수: 데이터 값(예: 숫자, 문자)을 직접 저장
- 포인터 변수: 다른 변수가 저장된 메모리 위치(주소)를 저장
포인터 변수 선언 방법
C 언어에서는 별표(*) 기호를 사용하여 포인터 변수를 선언합니다.
int *ptr; // int형 포인터 변수 선언 "ptr은 int형 변수의 주소를 저장할 수 있는 포인터 변수"라는 의미입니다.
int number = 10; int *ptr; // int형 변수의 주소를 저장할 수 있는 포인터 변수 선언 ptr = &number; // number의 주소를 ptr에 저장
- number는 값 10을 저장하는 일반 변수
- ptr은 number의 주소(0x1000)를 저장하는 포인터 변수
- ptr은 number를 "가리키고 있다"고 표현
3. 역참조 연산자(*)
역참조 연산자 *는 포인터가 가리키는 주소에 저장된 값을 가져옵니다.
- 저장된 메모리 주소를 따라가서 "그 장소에 누가 살고 있지?"라고 묻는 것과 같습니다.
int number = 10; int *ptr = &number; // number의 주소를 ptr에 저장 printf("%d", *ptr); // 출력: 10 (ptr이 가리키는 주소에 있는 값)
예시
#include <stdio.h> int main() { int age = 25; // 일반 변수 선언 및 초기화 // 주소 연산자 &: 변수의 메모리 주소를 알려줌 printf("age 변수의 값: %d\n", age); // 25 printf("age 변수의 주소: %p\n", &age); // 메모리 주소 (예: 0x7ffee40cbc4c) // 포인터 변수: 다른 변수의 주소를 저장 int *agePtr; // int형 포인터 변수 선언 // 포인트 변수로 선언을 해야지만 다른 변수의 주소를 담을 수 있음 agePtr = &age; // age의 주소를 agePtr에 저장 printf("agePtr에 저장된 주소: %p\n", agePtr); // age와 동일한 주소 // 역참조 연산자 *: 포인터가 가리키는 주소의 값을 가져옴 printf("agePtr이 가리키는 값: %d\n", *agePtr); // 25 // 역참조로 값 변경하기 *agePtr = 30; // agePtr이 가리키는 주소의 값(즉, age)을 30으로 변경 printf("변경 후 age의 값: %d\n", age); // 30 return 0; }
문자와 문자열에서의 활용
문자열에서도 같은 개념이 적용됩니다.
#include <stdio.h> int main() { char name[] = "John"; // 문자 배열(문자열) // 배열 이름 자체가 첫 번째 요소의 주소 printf("name의 주소: %p\n", name); printf("name[0]의 주소: %p\n", &name[0]); // 위와 동일 // 포인터로 문자열 다루기 char *namePtr = name; // name(즉, &name[0])의 주소를 namePtr에 저장 // 역참조로 첫 번째 문자 출력 printf("첫 번째 문자: %c\n", *namePtr); // J // 포인터 산술 연산: 다음 문자의 주소로 이동 printf("두 번째 문자: %c\n", *(namePtr+1)); // o return 0; }
코드를 한 줄씩 설명하면 아래와 같습니다.
char name[] = "John"; // 문자 배열(문자열)
이 줄은 "John"이라는 문자열을 저장하는 name이라는 문자 배열을 만듭니다. 메모리에는 다음과 같이 저장됩니다
- name[0]: 'J'
- name[1]: 'o'
- name[2]: 'h'
- name[3]: 'n'
- name[4]: '\0' (문자열 끝을 나타내는 널 문자)
printf("name의 주소: %p\n", name);
여기서 name은 배열의 이름입니다. C 언어에서 배열 이름은 그 배열의 시작 주소를 나타냅니다.
따라서 이 줄은 name 배열의 첫 번째 요소('J')가 저장된 메모리 주소를 출력합니다.
printf("name[0]의 주소: %p\n", &name[0]); // 위와 동일
&name[0]는 배열의 첫 번째 요소('J')의 주소를 명시적으로 가져옵니다. 이것은 위의 name과 정확히 같은 주소입니다.
💡 &은 ~의 주소 와 같은 말이라는 점 꼭 기억하기!char *namePtr = name; // name(즉, &name[0])의 주소를 namePtr에 저장
여기서는 포인터 변수(*) namePtr을 선언하고, (namePrt을 포인터 변수로 사용하겠다!!)
근데, 그 변수에 name 즉, &name[0]의 주소를 namePtr에 저장하겠다. 라는 뜻입니다.
name 배열의 시작 주소를 이 포인터에 저장합니다. 이제 namePtr은 'J'가 저장된 메모리 위치를 가리킵니다.printf("첫 번째 문자: %c\n", *namePtr); // J
*namePtr는 namePtr이 가리키는 메모리 위치에 저장된 값을 가져옵니다. 즉, 첫 번째 문자 'J'를 읽어옵니다.
printf("두 번째 문자: %c\n", *(namePtr+1)); // o
namePtr+1은 namePtr의 주소에 1을 더합니다. 이는 다음 문자('o')의 주소를 계산합니다. *(namePtr+1)은 그 주소에 저장된 값, 즉 'o'를 가져옵니다.
메모리를 시각화해서 보면 아래처럼 이해할 수 있습니다.
메모리 주소: 0x1000 0x1001 0x1002 0x1003 0x1004 +--------+--------+--------+--------+--------+ name 배열: | 'J' | 'o' | 'h' | 'n' | '\0' | +--------+--------+--------+--------+--------+
- name과 &name[0]는 모두 주소 0x1000을 가리킵니다.
- namePtr도 0x1000을 저장합니다.
- *namePtr는 0x1000 위치의 값인 'J'를 가져옵니다.
- namePtr+1은 0x1001을 가리킵니다.
- *(namePtr+1)은 0x1001 위치의 값인 'o'를 가져옵니다.
'IT 자격증 공부 > 정보처리기사' 카테고리의 다른 글
데이터 마이닝( Data Mining ) 이란? (0) 2023.09.26 OSI 7 참조 모델 중 다음이 설명하는 계층은? (0) 2023.09.26 트랜잭션(Transaction)의 주요 특성 4가지 (0) 2023.09.26 통신 프로토콜의 기본 요소 3가지 (0) 2023.09.26 네트워크 공격 유형 중 Land Attack 이란? (0) 2023.09.26