프로그래밍 언어/C언어

C언어 포인터 알아보기 입니다.

원원 2017. 10. 26. 23:07

안녕하세요. 오늘은 포인터(pointer)에 대해 알아보겠습니다.


변수 선언을 하면 메모리에 어떠한 값이 저장됩니다. 그러면 이때 이 메모리의 주소가 있고 그 주소를 가리키는게 포인터라고합니다.




- 주솟값의 실제 사용 예

위의 그림은 32bit MCU의 메모리맵입니다. 왼쪽 0x로 시작하는 부분은 주소이고 오른쪽은 그 주소에 저장된 데이터입니다. 

PortA를 제어하려면 0x40010c00주소와 offset을 더해서 제어하면 됩니다.


1
            (*(volatile unsigned *)0x40010c04)  |= 0x10;

cs

 (의미는 아래에 나옵니다.)


위의 코드는 실제로 주솟값을 가지고 코딩한 것입니다. 

근데 주솟값을 가지고 코딩을 하면 사용 할 때마다 찾아야 하므로 힘듭니다. 그래서 일반적인 컴파일러는 이러한 주솟값들을 단어로 치환시켜서 사용하거나 포인터를 사용합니다.



-포인터실제 사용

여기서 a_p의 변수가 포인터입니다. 왜냐하면 a_p변수가 a를 가리키고 있습니다.


char 형 변수 a의 값을 'A'라고 지정하면 0x0053FD0F의 주소에 1바이트로 'A'값이 저장됩니다.

char형포인터 a_p에 변수a의 주솟값을 넣어두면 0x0053FD00의 주소에 a의 주솟값이 저장됩니다.

(이때 저장되는 포인터의 크기는 사용하는 컴퓨터 비트에 따라 다릅니다. 32bit는 4바이트, 64bit는 8바이트. 추가적으로 64bit일지라도 운영환경으로 개발한 프로그램의 경우 32bit일 수도 있습니다. 이 글에서는 포인터의 크기는 4바이트라고 가정해서 합니다.)

**모든 포인터는 4바이트입니다




- 포인터 용어

포인터를 사용할때 사용하는 특수문자가 &와 *가 있습니다. 


&(ampersand)

변수의 시작주소를 표현할 때 사용합니다.

1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int main(void)
{
    char a = 'A';
    printf("a의 주소 : %p \n"&a);
 
    return 0;
}
cs


*(asterisk)

주솟값 안에 있는 내용을 표현할 때 사용합니다.

그러므로 *뒤에는 주솟값이 와야합니다.

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
int main(void)
{
    char a = 'A';
    printf("a의 값 : %c \n"*&a);
    
    return 0;
}
 
cs

&a의 값은 주솟값입니다. 여기에다가 *를 붙여서 내용을 출력하라 했으니까 'A'가 출력됩니다.



-포인터의 선언

포인터를 선언할 때는 *를 붙여서 선언합니다.

주소를 표현할 때는 &를 붙여서 표현합니다.



-메모리 관점에서 본 포인터

C언어를 사용할 때 int n= 256 이라고 하면 단순히 "int형 변수 n에 256을 저장한다." 라고 생각을 했었는데 이제 포인터를 배웠으니 int형 변수가 4바이트니까 4바이트에 값을 나눠서 저장한다고 생각 할 수 있습니다.



int n = 256

int형 변수 n은 256이 위와같은 형태로 저장되어 있을 것입니다.

각각의 주소는 1바이트(8비트)입니다. 256 = 0x10000000(16진수) 입니다. 

위와 같은 형태로 값이 저장됩니다.

*(char*)&n이란 

&n - n의 주소

(char*)(&n) - n의 주소를 char형 포인터로 변환(1바이트)

*(char*)(&n) - (char*)(&n)의 값


또한 실제로 값을 출력해보면 예상대로 나옵니다.





 (*(volatile unsigned *)0x40010c04)  |= 0x10;

주소를 찾아가서 0x10을 대입하라는 뜻입니다.

0x40010c04는 단순히 숫자인데 앞에 (volatile unsigned*)를 사용하여 포인터로 변환시키고 앞에 *를 붙여 주솟값 안에 있는 내용에 접근하란 뜻입니다.




예1)

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
int main(void)
{
    int n = 100;
    printf("%d \n", n);
    printf("%d \n"*&n);
    printf("%d \n"*&*&n);
    printf("%d \n"*&*&*&n);
 
    return 0;
}
cs


예2)

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
int main(void)
{
    int n = 0x444f4f47;
    printf("%c"*(char*)&n);
    printf("%c"*((char*)&+ 1));
    printf("%c"*((char*)&+ 2));
    printf("%c\n"*((char*)&+ 3));
    
 
    return 0;
}
cs