11 - 포인터

유현수·2024년 1월 16일
post-thumbnail

포인터 변수 선언

변수명 앞에 별표를 사용한다.

int* p

위 선언은 pint형을 갖는 object를 가리키는 포인터 변수라는 뜻이다.

주소 및 참조 연산자

C에선 오로지 포인터에서만 쓰이는 연산자 두 가지를 제공한다. 우선 변수의 주소를 찾기 위해 사용하는 & (주소) 연산자가 있다. x가 변수라면 &xx의 메모리 주소를 의미한다. 포인터가 가리키는 객체에 접근하고 싶다면 * (참조indirection) 연산자를 사용하면 된다. p가 포인터라면 *pp가 현재 가리키는 객체를 의미한다.

주소 연산자

포인터 변수의 선언은 포인터를 위한 공간은 설정해주나 어떤 객체를 가리키게 하지는 않는다.

int* p;    /* 가리키는 대상 없음 */

포인터를 사용하기 전에 반드시 초기화를 해주도록 하자.

int i;
int* p;

p = &i;

i의 주소를 주소 연산자 &를 사용해 포인터 변수 p에 할당해줌으로서 pi를 가리키게 된다.

포인터 변수를 선언할 때 초기화 해주는 것도 가능하다.

int i;
int* p = &i;

참조 연산자

포인터 변수가 객체를 가리키고 있다면 * (참조) 연산자를 통해 객체가 어떤 값을 갖는지 접근할 수 있다.

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

위 코드에서 printfi의 주소가 아닌 값을 출력할 것이다.

pi를 가리키는 한 *pi가명alias이다.

int i;
int* p;

p = &i;
i = 1;

printf("%d\n", i);  /* 1을 출력한다 */
printf("%d\n", *p); /* 1을 출력한다 */

*p = 2;

printf("%d\n", i);  /* 2를 출력한다 */
printf("%d\n", *p); /* 2를 출력한다 */

포인터 할당

C는 형만 같다면 할당 연산자가 포인터를 복사하는 것을 허용한다. i, j, p, q가 각각 다음과 같이 초기화가 되었다고 가정하자.

int i;
int j;
int* p;
int* q;

다음 구문은 포인터 할당의 예시다.

p = &i;

i의 주소가 p에 복사가 된다. 다음은 또 다른 포인터 할당의 예시다.

q = p;

구문은 p의 내용물(i의 주소)을 q에 복사해넣어 qp와 같은 공간을 가리키게 해준다.

1

pq 둘 다 i를 가리키므로 *p 혹은 *q에 새로운 값을 할당하면 i의 값 또한 달라진다:

*p = 1;

2

*q = 2;

3

같은 개체는 무한개의 포인터 변수가 동시에 가리킬 수 있다.

할당문

q = p;

*q = *p;

를 혼동하지 않도록 주의하라. 첫번째 구문은 포인터 할당이다. 두번째는 포인터 할당이 아니다. 다음 예제에서 확인해보라.

p = &i;
q = &j;
i = 1;

4

*q = *p;

5

할당문 *q = *pp가 가리키는 값(i의 값)을 q가 가리키는 개체(변수 j)에 복사해넣는다.

입력변수로서 포인터

#include <stdio.h>

void decompose(double x, long* int_part, double* frac_part)  /* 포인터를 입력변수로 받는다 */
{
    *int_part = (long) x;        /* int_part가 가리키는 객체에 값 저장 */
    *frac_part = x - *int_part;  /* frac_part가 가리키는 객체에 값 저장 */
}

int main(void)
{
    double x = 3.141592;
    long i;
    double d;
    
    decompose(x, &i, &d);  /* i, d의 포인터를 전달 */
    
    printf("i: %ld\n", i);
    printf("f: %f\n", d);
}

const로 입력변수 보호하기

함수에 변수에 대한 포인터를 전달해주면 보통 함수가 변수의 값을 수정한다고 이해할 수 있다.

f(&x);  /* f가 변수 x의 값을 수정했구나 짐작 가능 */

하지만 fx의 값을 수정하지 않는 경우도 간혹 있다. const라는 키워드를 통해 이를 명시적으로 선언할 수 있다.

void f(const int* p)
{
    *p = 0; /*** 컴파일 오류 ***/
}

반환값으로서 포인터

포인터를 반환하는 함수도 작성할 수 있다.

#include <stdio.h>

int* get_max(int* left, int* right)
{
    if (*left > *right) {
        return left;
    } else {
        return right;
    }
}

int main(void)
{
    int* p;
    int i = 3;
    int j = 4;
    
    p = get_max(&i, &j);
    
    printf("p is heading: %d\n", *p);
}
profile
"Life isn't about finding yourself. Life is about creating yourself."

0개의 댓글