본문 바로가기
Programming/C

포인터

by Tarake 2024. 8. 15.

포인터


메모리 주소


C언어를 포함해서 대부분의 언어는 변수를 생성하면 메모리 주소에 변수를 할당합니다. 메모리 주소는 변수가 저장된 메모리 위치입니다.  그래서 변수에 값을 저장하면 메모리 주소에 값이 저장됩니다. 다른 언어와 달리 C언어는 이런 메모리 주소에 접근할 수 있습니다.

& 키워드는 변수의 메모리 주소를 알아낼 때 사용됩니다.

 

int myAge = 43;
printf("%p", &myAge); // 출력 0x7ffe5367e044

메모리 주소는 16진수이기 때문에 0x--- 형식으로 출력됩니다.

 

 

포인터란?


포인터는 메모리에 있는 데이터의 주소를 가지고 있는 변수입니다. 

 

포인터 선언

int* num;
char* c;
float* f;

자료형*  변수이름; 으로 선언합니다.

 

int num = 10;
int* point = #

포인터를 선언하였으니 이제 포인터 변수를 다른 변수의 주소를 연결합니다. 메모리 주소에서 설명하였듯이 & 키워드를 사용하여 메모리 주소를 포인터 변수에 저장합니다.

 

포인터는 간접 참조를 할 수 있습니다. 변수에 *를 붙이면 됩니다. 

int num = 10;
int* point = #

printf("%d", *point);    // 10출력
printf("%u", point);     // num의 메모리 주소 출력

 

 

포인터와 배열


#include<stdio.h>

int main(void) {
    int a[] = {1, 2, 3, 4, 5};
    printf("%u\n", &a[0]);
    printf("%u\n", &a[1]);
    printf("%u\n", &a[2]);
    
    printf("%u\n", a);
    
    return 0;
}

위에 코드를 실행하면 배열이 메모리 상에서 연속된 주소를 가지는 것을 알 수 있습니다.

 

배열에 포인터를 사용하면

#include<stdio.h>

int main(void) {
    int a[] = {1, 2, 3, 4, 5};
    printf("%d", *a);    // 1 출력
    printf("%d", *(a + 1));    // 2출력
    
    return 0;
}

*a를 출력하면 a[0]이 출력되고 *a+1은 a[1]이 출력되는 것을 알 수 있습니다. 즉 a + i는 &a[i]와 같다라고 할 수 있습니다. 또한*(a + i)는 a[i]와 같다고 할 수 있습니다.

 

포인터를 배열처럼 사용할 수 있습니다.

#include <stdio.h>

int main(void) {
    int a[] = {1, 2, 3, 4, 5};
    int *p;
    
    p = a;
    printf("%d %d %d\n", a[0], a[1], a[2]);    // 1 2 3
    printf("%d %d %d\n", p[0], p[1], p[2]);    // 1 2 3
    
    p[0] = 6;
    p[1] = 7;
    p[2] = 8;
    
    printf("%d %d %d\n", a[0], a[1], a[2]);    // 6 7 8
    printf("%d %d %d\n", p[0], p[1], p[2]);    // 6 7 8
    
    return 0;
}

포인터를 배열처럼 사용할 수 있고 값을 변경이 가능합니다.

 

 

이중 포인터


int i = 10;
int *p = &i;
int **q = &p;

 

포인터는 변수의 메모리 주소 값을 가지는 변수입니다. 포인터가 포인터를 가리킬 수 있습니다. 포인터의 포인터 또는 이중 포인터라고 합니다. *기호를 하나만 쓰면 보통 포인터 **를 쓰면 이중 포인터가 됩니다.

 

 

포인터배열


포인터를 배열처럼 사용할 수 있습니다.

int* a[5];

[]연산자가 우선순위가 *보다 높기 때문에 a는 배열이되고 int *들의 배열이 됩니다. 즉 정수를 가리키는 포언터들의 배열이 됩니다.

int a = 1, b = 2, c = 3;
int abc[3] = { &a, &b, &c};

포인터 배열에 대입연산자를 사용해서 각 변수들의 주소를 넣어주면 됩니다.

 

포인터 배열이 가장 많이 사용되는 형태는 문자형 배열입니다.

char str[3][10] = {
    "aaaaaaa",
    "bbbb",
    "cccccccc"
};

배열에 문자열을 여러개 저장해야할 때 문자열 길이가 10인 배열을 선언했는데 5개 밖에 쓰지 않는다면 나머지 5개의 배열 크기는 메모리 공간의 낭비가 됩니다. 하지만 문자열 배열은 각 행의 길이가 가변적이라 공간에 낭비가 없습니다.

char *a[3] = {
    "aaaa",
    "bbbbbb",
    "ccccccccc"
};

이런식으로 문자열을 저장하면 각 문자열의 길이가 달라도 메모리의 낭비가 없습니다.

 

 

함수 포인터


함수 또한 실행이 시작되는 주소를 가지고 있습니다. 때문에 이 주소 또한 포인터에 저장할 수 있습니다. 이렇게 포인터에 저장된 함수 주소를 이용하면 함수를 실행할 수 있습니다. 함수를 가리키는 포인터를 함수 포인터라고 합니다.

#include<stdio.h>

int add(int x, int y) {
    return x + y;
}
int main(void) {
    int result;
    int (*pf)(int, int);    // 함수 포인터 정의

    pf = add;
    result = pf(10, 20);
    printf("%d", result);

    return 0;
}

 

 

출처

W3school

 

W3Schools.com

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

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

구조체  (0) 2024.08.28
문자열과 boolean  (0) 2024.08.15
배열  (0) 2024.08.15
break문과 continue문  (0) 2024.08.15
반복문  (0) 2024.08.14