일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 27 | 28 | 29 | 30 | 31 |
- shell_script
- HTML #핵심정리
- C언어 # 핵심 정리
- C언어 # 부록
- PHP #핵심정리
- Bandit
- C언어 #핵심정리
- C++ 언어 # 핵심 정리
- C++ 언어 #핵심정리
- Hacking #Baic
- MySQL #핵심정리
- C언어 #부록
- C++ 언어 # 핵심정리
- Today
- Total
cCcode
C Language [핵심정리] - 11 본문
1. 포인터 사용하기
지금까지 값을 저장할 때 변수를 사용했습니다. 그럼 근본적인 의문이 생길텐데요.
Q. "과연 변수는 어디서 생성되는 것일까요?"
A. "변수는 컴퓨터의 메모리에서 생성됩니다. 즉, 메모리에 일정한 공간을 확보하고 원하는 값을 저장하거나 가져오는 방식이죠."
보통 변수는 num과 같이 변수명을 사용해 표현하지만 방금 말했듯이 변수는 메모리의 특정 공간에 위치해 있기 때문에 메모리 주소로도 표현이 가능합니다. 그래서 변수의 메모리 주소를 구하려면 변수 앞에 &(주소 연산자)를 사용하면 됩니다. 아,, 그리고 메모리 주소는 16진수 형태이기 때문에 %x, %X 서식지정자를 사용합니다. + 물론 서식지정자 %p(pointer의 약어로 p를 사용)를 사용해도 됩니다. 이때 메모리 주소는 고정된 것이아니라, 컴퓨터 마다, 실행할 때마다 달라져요.
시스템이 32bit인지 64bit인지에 따라 메모리 주소의 범위도 달라집니다.
1) 32bit : 16진수 6자리 2) 64bit : 16진수 16자리
32bit에서는 6자리가 나오고, 64bit에서는 16자리가 나오는 이유를 알기 위해선 컴퓨터의 처리 단위를 알아야 합니다.
4bit는 16진법의 기본 단위입니다. 16진법의 한 자릿수를 2진법 네 자릿수로 표기할 수 있기 때문입니다.
10진수의 관점에서 봐도 최소 4비트는 있어야 10진수 한 자릿수를 표기할 수 있습니다. 우리가 평소에 사용하는 10진수의 한 자릿수를 표현한다는 점에서 4bit는 상당히 의미가 있는 정보단위 입니다. 여튼 16진법은 기본단위가 4bit가 되기 때문에 64bit 환경에서 64 / 4 = 16으로 16자리가 출력됩니다.
제 시스템은 64bit 이므로 결과로 16진수 16자리가 출력되었습니다. 그래서 앞으로 16진수 8자리 또는 16자리가 나온다면 대부분 메모리 주소라고 생각하시면 됩니다.
[warning C4477: 'printf' : 서식문자열 '%x'에 'unsigned int' 형식의 인수가 필요하지만 variadic 인수 1의 형식이 'int *' 입니다.] 주소를 %x로 출력하게 되면 이와 같은 경고가 발생합니다. 그러면 그전에 했던것처럼 해당 서식지정자에 필요한 형식으로 형변환 해주면 됩니다. 여기서는 'unsigned int' 형식이 되겠네요.
경고를 감안하고 컴파일 해서 결과를 보면 4개의 값 모두 동일합니다. 그러니까 'unsigned int'로 형변환 해준다고 해서 값의 손실이 일어난다는 건 아니라는 뜻입니다.
C언어에서 메모리 주소는 포인터(pointer)변수에 저장합니다. 다음과 같이 포인터 변수는 자료형 뒤에 *(Asterisk)를 사용합니다. • 자료형 *포인터명; • 포인터 = &변수;
포인터는 메모리의 특정 위치를 가리킬 때 사용합니다.
이 때 pointer은 7이 저장된 메모리 공간을 가리킵니다. 즉, 변수 number이 있는 공간을 가리키게 되는 것이죠.
sizeof 연산자로 포인터의 크기를 구해보면
• 32bit일 때 4byte • 64bit일 때 8byte 입니다.
2. 역참조 연산자 사용하기
포인터 변수에는 메모리 주소가 저장되어 있습니다. 이 때 메모리 주소가 있는 곳으로 이동해 값을 가져오고 싶다면 역 참조(dereference)연산자 *를 사용합니다. ◦ * 포인터
역참조를 해서 가져온 값은 int 이므로 %d 서식지정자를 사용합니다.
이처럼 * 포인터 = 값; 을 이용해 포인터 변수가 가지고 있는 메모리 주소에 저장된 값을 수정할 수 있습니다.
위 코드처럼 작성할 경우 아래와 같은 경고가 발생합니다.
[warning C4047 : '=' : 'int *'의 간접 참조 수준이 'int'과(와) 다릅니다.]
포인터를 다루시다보면 종종 이런 경고를 보실 수 있을텐데, 이런 경우에서는 역참조 연산자(*)나 주소연산자(&) 이용해 두 자료형을 일치시켜주면 됩니다.
- 정리 -
(1) 변수는 메모리 주소를 몰라도 값을 가져오거나 저장할 수 있다.
(2) 주소 연산자(&)는 변수의 메모리 주소를 구한다.
(3) 역참조 연산자(*)는 메모리에 저장된 값에 접근할 수 있다. 즉, 메모리 주소에 접근하여 값을 가져오고 저장한다.
(4) 포인터는 변수의 메모리주소만을 가리킨다.
3. 다양한 자료형의 포인터 선언
다양한 자료형의 포인터를 선언해보겠습니다.
C에서 사용하는 모든 자료형은 포인터로 만들 수 있습니다. 그런데 따로 포인터 자료형을 만들지 않은 이유는 포인터에 저장된 메모리 주소값은 정수형으로 동일하지만 선언하는 자료형에 따라 메모리에 접근하는 방법이 달라지기 때문입니다. ex) long long 포인터는 8byte 크기만큼 char 포인터는 1byte 크기만큼 값을 가져오거나 저장합니다.
4. 상수와 포인터
포인터에도 const(상수)키워드를 사용할 수 있습니다. 다만 여기서는 const의 위치에 따라 특성이 달라집니다.
1) 상수를 가리키는 포인터(pointer to constant)
2) 포인터 자체가 상수인 상황(consatnt pointer)
이 경우에는 포인터변수 안에 들어있는 메모리 주소 자체를 변경할 수는 없지만 이미 저장된 주소를 이용해 변수의 값을 수정할 수는 있다.
3) 포인터가 상수이며, 상수를 가리키는 상황 (constant pointer to constant)
이 때는 포인터를 선언하는 자료형에도 const를 사용하고 * 뒤에도 const를 사용합니다.
'C Language Basic' 카테고리의 다른 글
C Language [핵심정리] - 12 + ∂ (0) | 2021.05.17 |
---|---|
C Language [핵심정리] - 12 (0) | 2021.05.16 |
C Language [핵심정리] - 10 (0) | 2021.05.14 |
C Language [핵심정리] - 9 (1) | 2021.05.14 |
C Language [핵심정리] - 8 (0) | 2021.05.13 |