사이먼's 코딩노트

[C언어] 포인터 본문

C언어

[C언어] 포인터

simonpark817 2024. 2. 2. 13:05

[포인터]

[컴퓨터의 구성]

1. CPU : 연산 기능

  • 데이터 처리속도 : 매우 빠름
  • Read / Write 속도 : 매우 빠름

 

2. L1 Cache(캐시) 메모리 : 저장 기능

  • 저장용량 : 작음 (보통 8 ~ 64KB)
  • Read / Write 속도 : 매우 빠름 (L2보다 빠름)

3. L2 Cache 메모리 : 저장 기능

  • 저장 용량 : 작음 (보통 64KB ~ 4MB)
  • Read / Wrtie 속도 : 매우 빠름

 

4. 메모리 : 저장 기능

  • 저장 용량 : 작음 (8GB)
  • Read / Write 속도 : 빠름

 

5. 하드디스크 : 저장 기능

  • 저장 용량 : 큼
  • Read / Write 속도 : 느림

 

6. PC를 관리하는 소프트웨어 : 운영체제(OS)

  • OS가 메모리를 관리한다.
  • 우리가 만든 C 프로그램은 운영체제의 관리하에 실행된다.
  • 즉, 우리가 만든 프로그램은 운영체제에 메모리를 구걸한다.
  • 우리가 만든 변수는 메모리에 할당된다. 예를 들어 우리가 변수에 숫자 10을 넣으면, 그것은 메모리 어딘가에 저장된다.

 

  • 메모리는 크게 2개의 구역으로 나뉜다.
  • 힙은 객체들의 세계, 위에서 내려온다.
  • 스택은 지역변수들의 세계, 아래에서 올라간다.

 

[포인터의 구조]

  • 포인터는 메모리 상 데이터가 저장되어 있는 주소값이다.
  • 포인터 변수는 포인터 값을 저장하는 변수일 뿐이다.
#include <stdio.h>

void pointerPlus(int *num) {
  *num += 5;
}

void numPlus(int num) {
    num += 5;
}


int main() {

    int* p1;
    int * p2;
    int *p3;

    int a = 15;

    p1 = &a;

    printf("변수 a의 값 : %d\n", a);
    printf("int변수 a의 주소 : %d\n", &a);
    printf("포인터변수 p1의 값 : %d\n", p1);
    printf("p1 주소에 들어있는 실제 값 : %d\n", *p1);


    int *p = NULL;
    int num = 15;

    p = &num;

  *p += 5;

    printf("%d\n", *p);
    printf("%d\n", num);

    (*p)++;
    printf("%d\n", *p);

    *p++;
    printf("%d\n", *p);



    int num2 = 15;

    numPlus(num2);
    printf("numPlus 사용 : %d\n", num2);

    pointerPlus(&num2);
    printf("pointerPlus 사용 : %d\n", num2);

    return 0;
}
  • p1, p2, p3는 포인터 변수이며, 포인터 변수를 선언할 때는 타입에 맞춰 *을 붙혀준다.
  • 각 포인터 변수에는 값이 아닌 주소값이 들어간다.
  • 정수 a에는 15라는 값이 들어가 있지만, &a 와 같이 15를 가진 a의 실제 주소값은 159943921924와 같은 주소값이 들어있다.
  • p1 = &a; 같이 작성하면 p1에는 a의 주소가 들어간다.
  • p1의 주소로 가서 값을 보기 위해서는 *p로 출력문을 출력해보면 된다. 여기서 *의 뜻은 해당 주소로 간다. 라는 의미이다.

 

  • 포인터 변수인 p는 15라는 정수를 가진 num의 주소인 &num를 가지고있다.
  • *p += 5; 는 직접 num에 접근하지 않고 이미 포인터 변수인 p가 num의 주소를 가지고 있기 때문에 *p를 통해 해당 주소로 이동해서 가지고 있는 15라는 값에 5를 더한다는 의미이다.
  • 그렇게 되면 출력문을 통해 *p나 num을 출력해보면 둘 다 20이라는 값을 가지고있다.

 

  • 현재까지 p는 20이라는 정수 값을 가지고 있다.
  • (*p)++; 연산은 포인터 변수인 p의 주소로 가서 1을 증가하기 때문에 값이 21이 된다.
  • *p++; 연산은 ++ 연산자가 더 우선적으로 계산이 되기 때문에 포인터 변수인 p의 주소값에 1을 더하고 해당 주소의 값을 출력한다.
  • 주소값에 1을 더하면 기존 num을 주소를 가르키는 p가 아닌 새로운 주소를 가르키기 때문에 해당 주소에 가서 값을 출력해보면 아무것도 들어있지 않다.

 

  • 이렇게 직접 변수에 접근하지 않고 원하는 값을 컨트롤하기 위해서 포인터를 사용한다.

 

[포인터타입 변수의 크기]

#include <stdio.h>

int main(void) {
    // 정수 계열
    char* c;
    short* s;
    int* i;
    long* l;

    // 실수 계열
    float* f;
    double* d;

    // 여기서 구현
    printf("sizeof char : %lu\n", sizeof(char));
    // 포인터변수는 타입과 상관없이 크기가 무조건 8바이트이다.
    printf("sizeof char : %lu\n", sizeof(c));

    printf("sizeof short : %lu\n", sizeof(short));
    printf("sizeof short : %lu\n", sizeof(s));

    printf("sizeof int : %lu\n", sizeof(int));
    printf("sizeof int : %lu\n", sizeof(i));

    printf("sizeof long : %lu\n", sizeof(long));
    printf("sizeof long : %lu\n", sizeof(l));

    printf("sizeof float : %lu\n", sizeof(float));
    printf("sizeof float : %lu\n", sizeof(f));

    printf("sizeof double : %lu\n", sizeof(double));
    printf("sizeof double : %lu\n", sizeof(d));

    return 0;
}
  • 위 코드에서 각 변수는 포인터 변수들이다.
  • 정수 계열과 실수 계열의 크기를 sizeof를 통해 출력한 출력문이다.
  • 출력문을 통해 각 타입별로 크기를 출력해보면 정수 계열인 char는 1바이트, short는 2바이트, int는 4바이트, long은 8바이트이다.
  • 실수 계열인 float은 4바이트, double은 8바이트이다.
  • 하지만 각 타입에 맞는 포인터 변수들의 크기를 출력해보면 모두 8바이트를 나타낸다.
  • 포인터 변수들은 주소를 나타내기 때문에 크기가 모두 8바이트이다. 하지만 해당 주소로 이동했을 때의 값들이 서로 다른 타입을 가지고있다는 것이다.
반응형

'C언어' 카테고리의 다른 글

[C언어] 다중 포인터  (0) 2024.02.06
[C언어] 포인터 문제풀이  (0) 2024.02.02
[C언어] 함수 문제풀이(2) / 서식지정자와 자료형  (0) 2024.01.29
[C언어] 함수 문제풀이(1)  (0) 2024.01.24
[C언어] 함수  (1) 2024.01.23