C 프로그래밍에서 16진수와 메모리 주소 이해하기: 포인터와 역참조까지

현재시각 새벽 4시. 오늘은 C 프로그래밍에서 중요한 개념인 메모리 주소와 16진수에 대해 기록해보고자 한다(: 처음 배우는 사람이라면 조금 어려울 수 있지만, 차근차근 따라오면 누구나 이해할 수 있다. 이제부터 하나씩 풀어보자.
1. 16진수란 무엇일까?
16진수(Hexadecimal)는 우리가 평소 사용하는 10진수(Decimal)나 2진수(Binary)와는 조금 다른 숫자 체계다. 컴퓨터는 사실 0과 1만을 이해할 수 있기 때문에, 우리가 하는 모든 작업은 결국 0과 1로 변환되어야 한다. 그런데 2진수는 너무 길어서 다루기 불편하다. 그래서 2진수를 간편하게 표현할 수 있는 16진수가 많이 사용된다.
- 10진수는 우리가 일반적으로 사용하는 숫자 체계다. 예를 들어, 10진수에서 10은 10을 의미한다.
- 2진수는 0과 1만을 사용하는 숫자 체계다. 예를 들어, 2진수에서 10은 2를 의미한다.
- 16진수는 0부터 15까지의 값을 사용한다. 그런데 10 이상은 A부터 F까지로 표현한다. 즉, 10은 A, 11은 B, 15는 F다.
왜 16진수가 중요할까?
16진수는 2진수를 간단하게 표현할 수 있기 때문에 컴퓨터에서 데이터를 처리할 때 아주 유용하다. 예를 들어, 컴퓨터는 모든 데이터를 2진수로 저장하는데, 이 2진수를 16진수로 바꾸면 훨씬 간단하게 다룰 수 있다. 그래서 메모리 주소나 데이터 값을 16진수로 표현하는 경우가 많다.
2. 10진수, 2진수, 16진수 변환
그럼 10진수를 16진수로 바꾸는 방법을 한 번 살펴보자.
예시: 255 216 255
- 10진수로 표현한 값: 255 216 255
- 이 값을 2진수로 바꾸면:
255 → 11111111
216 → 11011000
255 → 11111111 - 그런데 2진수는 너무 길어서 불편하다. 그래서 이 값을 16진수로 바꾸면 훨씬 간단해진다.
255는 FF, 216은 D8, 다시 255는 FF다.
그래서 255 216 255를 16진수로 표현하면 이렇게 된다: 0xFFD8FF.
여기서 0x는 16진수 표기법을 나타내는 접두사다. 즉, 숫자가 16진수임을 명확히 하기 위해 앞에 0x를 붙인다.
3. 메모리 주소란 무엇일까?
메모리 주소는 컴퓨터 메모리에서 특정 위치를 가리키는 값이다. C에서 변수를 선언하면 그 변수는 메모리 어딘가에 저장되는데, 그 저장된 위치를 메모리 주소라고 부른다.
예를 들어, 변수를 선언하고 값을 저장한 후:
#include <stdio.h> int main(void) { int n = 50; printf("%p\n", &n); // n의 메모리 주소를 출력 }
위 코드에서 &n은 변수 n의 메모리 주소를 얻는 연산자다. %p는 포인터(주소)를 출력할 때 사용하는 형식 지정자(format specifier)로, 결과는 0x7ffe00b3adbc처럼 16진수로 나타난다. 이는 컴퓨터 메모리의 특정 주소를 의미한다.
여기서 %p는 형식 지정자(format specifier)이고, &n은 인자(argument)다. printf를 사용할 때는 형식 지정자에 맞는 인자를 제공해야 한다. 만약 printf("%p\n");처럼 &n을 생략하면, 올바른 결과가 나오지 않는다.
4. 포인터와 역참조 연산자
메모리 주소를 잘 활용하면 효율적인 프로그램을 만들 수 있다. 예를 들어, 포인터를 이용하면 변수의 주소를 참조하고 그 값을 쉽게 변경할 수 있다.
#include <stdio.h> int main(void) { int n = 50; int *ptr = &n; // n의 주소를 ptr에 저장 printf("n의 값: %d\n", *ptr); // ptr을 통해 n의 값에 접근 *ptr = 100; // n의 값을 변경 printf("변경된 n의 값: %d\n", n); // 100으로 변경된 값 출력 }
이 코드는 포인터 ptr을 사용하여 n의 값을 수정하고 있다. 처음 n은 50이었지만, 포인터를 통해 100으로 변경되었다.
여기서 *ptr에서 *은 역참조 연산자(dereference operator)로, 포인터가 가리키는 메모리의 값을 가져오는 역할을 한다. &는 주소 연산자(address-of operator)로, 변수의 메모리 주소를 반환한다. 즉,
- &n → n의 메모리 주소를 가져옴.
- *ptr → ptr이 가리키는 주소의 값을 가져옴.
또한 %d와 %i는 모두 정수(int) 값을 출력하는 형식 지정자다. 둘 다 거의 동일하게 사용되지만, %i는 입력받을 때 10진수, 8진수, 16진수를 자동으로 감지하는 특징이 있다.
예를 들어,
int num; scanf("%i", &num);
이렇게 하면 0x로 시작하면 16진수로, 0으로 시작하면 8진수로, 그냥 숫자만 입력하면 10진수로 인식한다. 하지만 출력할 때는 %d와 %i 모두 같은 역할을 한다.
5. 포인터와 변수의 관계
왜 ptr을 사용하여 n의 값을 수정할까?
ptr을 사용하여 n의 값을 수정하는 이유는 포인터의 개념 때문이다. 포인터는 메모리 주소를 가리키는 변수로, 이 주소를 통해 간접적으로 값을 수정할 수 있다.
예를 들어, int *ptr = &n;은 ptr이 n의 주소를 가리키게 해. 그 후 *ptr을 사용하면 ptr이 가리키는 주소에서 값을 직접 수정할 수 있다. n의 값을 수정할 때 ptr을 통해 수정하는 이유는 효율성 때문이다. 큰 데이터나 구조체 같은 경우, 값을 직접 복사하는 것보다 메모리 주소를 통해 간접적으로 수정하는 것이 성능상 유리하기 때문이다.
정리하자면:
- ptr은 변수로, 메모리 주소를 저장하는 역할을 한다.
- *ptr은 역참조 연산자로, 포인터가 가리키는 메모리 주소에 저장된 값을 불러온다.
포인터를 활용한 이유는 데이터를 간접적으로 접근하고 수정할 수 있기 때문이다. 또한, *ptr은 변수가 아닌 ptr이 가리키는 메모리 주소에 있는 값을 의미한다.
언제 이런 것이 사용될까?
- 메모리 주소와 포인터는 주로 효율적인 메모리 관리가 필요한 시스템 프로그래밍, 운영체제, 임베디드 시스템 등에서 사용된다. 예를 들어, 대형 데이터 구조나 동적 메모리 할당이 중요한 상황에서, 포인터를 사용해 메모리의 주소를 직접 다루면 성능이 향상된다.
- 16진수는 특히 디버깅과 메모리 분석에서 많이 사용된다. 예를 들어, 메모리 주소나 바이너리 데이터를 분석할 때 16진수로 표기하면 읽기가 훨씬 편리하다. 특히, 컴퓨터 시스템에서 데이터를 저장하고 처리하는 방식이 2진수이기 때문에, 이를 쉽게 다루기 위해 16진수를 많이 사용한다.
이제 16진수와 메모리 주소가 무엇인지, 그리고 어떻게 활용할 수 있는지 좀 더 명확히 이해할 수 있을 것이다(: C 프로그래밍에서 메모리와 데이터가 어떻게 처리되는지 이해하는 것은 매우 중요하니, 오늘 배운 내용을 잘 기억해두자🥰.
'IT' 카테고리의 다른 글
C 언어에서 string이 없는 이유 – 문자열과 포인터의 관계 (0) | 2025.03.30 |
---|---|
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교 (0) | 2025.03.28 |
병합 정렬(Merge Sort) : 효율적인 정렬 알고리즘 배우기 (0) | 2025.03.25 |
C 언어로 재귀와 반복문을 사용한 피라미드 그리기 (0) | 2025.03.24 |
정렬 알고리즘 완벽 이해: Big O와 Big Ω로 실행 시간 최적화하기(: (0) | 2025.03.24 |
댓글
이 글 공유하기
다른 글
-
C 언어에서 string이 없는 이유 – 문자열과 포인터의 관계
C 언어에서 string이 없는 이유 – 문자열과 포인터의 관계
2025.03.30 -
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교
2025.03.28 -
병합 정렬(Merge Sort) : 효율적인 정렬 알고리즘 배우기
병합 정렬(Merge Sort) : 효율적인 정렬 알고리즘 배우기
2025.03.25 -
C 언어로 재귀와 반복문을 사용한 피라미드 그리기
C 언어로 재귀와 반복문을 사용한 피라미드 그리기
2025.03.24
댓글을 사용할 수 없습니다.