카메라 개발자 공부방(SW)

[10장] 포인터 본문

Langauge/C

[10장] 포인터

luckmart 2021. 9. 29. 20:05
반응형

자 오늘은 대망의 포인터 변수를 시작할 차례입니다.

오늘 하는 내용이 어렵게 느껴진다면 [9장] 변수와 주소를 꼭 복습해주세요.

 

포인터 변수는 주소를 저장하는 메모리 공간입니다.

포인터 변수도 변수기 때문에 메모리 공간(값)이 변경될 수 있고, 그 메모리에 접근할 수 있는 이름도 가지고 있습니다.

 

다음 코드를 보시죠

#include <stdio.h>

int main()
{
    int n = 10;
    int* pn = &n;
    printf("%d %p %p\n", 10, &n, pn);
    return 0;
}

// 실행결과
// 10 008FF91C 008FF91C

메모리 그림

n이라는 메모리 공간의 시작 주소가 pn이라는 메모리 공간에 저장이 된 것입니다.

이때 포인터 변수 pn은 n이라는 메모리 공간을 가리킨다 라고 이야기할 수 있습니다.

 

9장의 내용을 복습하면 * 연산자로 주소가 참조하는 메모리 공간 자체를 접근할 수 있다고 배웠습니다.
int형 포인터 이기 때문에 *로 주소를 참조하면 시작 주소를 기점으로 4바이트만큼만 int data type으로 메모리 공간을 인식하게 됩니다.

#include <stdio.h>

int main()
{
    int n = 10;
    int n1 = 30;
    int* pn = &n;
    pn = &n1;

    printf("%d %p %p %p\n", 10, &n, pn, &n1);
    return 0;
}

// 실행결과
// 10 008FF91C 0085F870 0085F870

포인터 변수 또한 변할 수 있는 메모리 공간이기 때문에 위의 예제처럼 다른 값으로 변경 시 킬 수 있습니다.
pn이 초기화될 땐 n을 가리키다가 그다음 라인에서 n1을 가리키고 있습니다.

#include <stdio.h>

int main()
{
    int n = 10;
    int* pn = &n;
    printf("%d %d\n", n, *pn);
    return 0;
}

// 실행결과
// 10 10

9장에서 어떤 공간의 메모리를 안다라는건 그 주소를 통해 그 메모리 공간 자체를 읽을 수 있고, 값 자체도 변경시킬 수 있다고 배웠습니다.
위의 코드는 *연산자를 통해 주소가 가리키는 값을 read 한 예제입니다.

메모리 그림

 

자 이번엔 포인터 변수를 이용해 값을 변경시켜보겠습니다.

#include <stdio.h>

int main()
{
    int n = 10;
    int* pn = &n;

    printf("%d %d\n", n, *pn);
    *pn = 30;
    printf("%d %d\n", n, *pn);
    return 0;
}

// 실행결과
// 30 30

pn이 참조하는 메모리 공간을 = 대입 연산자를 통해 메모리 값을 변경되었습니다.

당연히 pn에 저장된 주소는 n의 주소이기 때문에, (*pn)으로 참조하는 메모리를 변경시키면 n 자체의 데이터 값이 변경이 됩니다.

#include <stdio.h>

int main()
{
    int n = 10;
    int* pn = &n;
    pn += 1;
    *pn = 30;

    printf("%d %d\n", 10, *pn);
    return 0;
}

// 실행결과
// run time error!

그리고 포인터를 사용할 땐 주의해야될 부분이 있는데요.
위의 코드는 문제가 되는 코드인데, 왜 run time error가 발생했을까요?

 

산술 연산로 포인터 주소를 이동하였지만, 메모리 공간은 할당되지 않은 상태입니다!

그런데 다른 값으로 메모리 공간에 쓰려고 하니 문제가 발생을 한 것인데, 이것이 왜 문제일까요?

그 주소로 시작하는 메모리가 운이 좋아서 다른 프로세서나 운영체제에서 쓰고 있지 않았던 상태면 다행이지만, 

원래 쓰고 있었던 메모리라면, 연산에 큰 문제를 일으킬 여지가 있기 때문에 운영체제 단에서 예외를 발생시킨 것입니다.

 

다음은 포인터 변수의 크기에 대한 예제입니다.

#include <stdio.h>

int main()
{
    printf("%d\n", sizeof(char));
    printf("%d\n", sizeof(int));
    printf("%d\n", sizeof(float));
    printf("%d\n", sizeof(double));

    printf("%d\n", sizeof(char*));
    printf("%d\n", sizeof(int*));
    printf("%d\n", sizeof(float*));
    printf("%d\n", sizeof(double*));

    return 0;
}

// 실행결과 (32bit 운영체제)
// 1
// 4
// 4
// 8

// 4
// 4
// 4
// 4

// 실행결과 (64bit 운영체제)
// 1
// 4
// 4
// 8

// 8
// 8
// 8
// 8

 

32비트 운영체제에서 표현할 수 있는 가짓수는 4byte = 32bit이기 때문에 포인터 변수의 크기가 4byte입니다.

반대로 64비트 운영체제에선 8byte = 64bit이기 때문에 포인터 변수의 크기가 8byte입니다.

 

운영체제의 비트 수와 포인터 변수로 표현할 수 있는 비트 수는 동일한데요. 우리가 램 크기가 4GB 넘을 때, 64bit 운영체제를 깔아야 하는 이유와 같습니다.(2^32 = 4GB입니다.) 32bit 운영체제에서 이것보다 더 큰 램을 사용하는 경우엔 표현할 수 있는 비트가 부족하기 때문에 초과분의 램에 대해선 무용지물입니다!.
램이 4GB가 넘는 다면 반드시 64비트 운영체제를 깔아야겠죠?

 

자 오늘은 여기까지입니다.

'Langauge > C' 카테고리의 다른 글

[12장] 포인터와 배열  (0) 2021.10.01
[11장] 배열  (0) 2021.09.30
[9장] 변수와 주소  (0) 2021.09.28
[8장] 사용자 함수  (0) 2021.09.27
[7장] 변수의 초기화와 대입  (0) 2021.09.26
Comments