[C++] 포인터

haaana·2023년 12월 6일
0



8. 포인터


8.1 포인터

📌 포인터

변수는 할당된 메모리 공간에 붙여진 이름이다. 그리고 그 변수명을 통해 메모리 공간에 접근할 수 있다.

포인터 란 메모리의 주소를 갖고 있는 변수를 말한다.
포인터 변수 라고도 부른다.

포인터를 통해 메모리의 내용에 직접적으로 접근할 수 있다.
→ 그 주소에 있는 값으로 가라!

포인터는 왜 필요한가?

포인터를 사용하면 프로그램의 속도 향상이 가능하다.
함수에도 적용 가능하다.

📌 포인터 연산자

포인터에서 사용되는 연산자는 다음과 같다.

주소 연산자 &

& 연산자는 변수의 이름 앞에 사용하며, 해당 변수의 주소값을 가져온다.

참조 연산자 *

* 연산자는 포인터의 이름이나 주소 앞에 사용하며, 포인터가 가리키는 값을 가져온다.

📌 선언 & 초기화

포인터의 선언은 데이터형 * 변수명 ; 순으로 한다.

포인터가 선언된 후에 포인터에 접근하기 위해 변수가 반드시 있어야 한다.

포인터를 선언한 후 * 연산자를 사용하기 전에 포인터는 반드시 초기화되어야 한다.
→ 포인터의 선언과 동시에 초기화를 하는 것이 좋다.

데이터형을 반드시 일치시켜야 한다.
→ 포인터 변수는 항상 4byte이다.

포인터의 선언과 초기화를 동시에 하는 방법은 다음과 같다.
데이터형 * 포인터명 = & 변수명 ;
데이터형 * 포인터명 = & 주소값 ;

포인터를 선언할 때 * 연산자의 앞과 뒤에 존재하는 공백은 무시된다.

다음은 포인터 선언의 예시이다.

#include <iostream>

using namespace std;

int main() {
    int num = 10;       // 변수의 선언
    int *ptr = &num;    // 포인터의 선언, num의 메모리 주소를 포인터 변수 ptr에 저장

	printf("num: %d\n", num);		// num의 값
    printf("&num: %#x\n", &num);	// num의 주소값
    printf("ptr: %#x\n", ptr);		// ptr의 값
    printf("&ptr: %#x\n", &ptr);	// ptr의 주소값
    printf("*ptr: %d\n", *ptr);		// 역참조 연산자 * 사용
    
    return 0;
}

& 연산자는 num 변수가 할당된 메모리의 시작 주소(0x6dc1b0a8)를 반환한다.

포인터 ptrnum 변수의 주소(0x6dc1b0a8)를 저장했기 때문에 포인터 ptr 을 출력하면 num 변수의 주소(0x6dc1b0a8)가 출력된다.

포인터 ptr 의 주소값을 출력하면 새로운 주소(0x6dc1b0a0)가 출력된다.

* 연산자를 사용하여 *ptr 을 출력하면 num 변수의 값(10)이 반환된다.

C++에서는 여러 개의 포인터를 동시에 선언할 수 있다.

int *ptr1, ptr2;	// ptr1은 int형 포인터, ptr2는 그냥 int형 변수로 선언
int *ptr1, *ptr2;	// ptr1, ptr2 모두 int형 포인터로 선언

📌 역참조

포인터와 역참조

포인터를 선언할 때와 역참조를 할 때 모두 * 연산자를 사용한다.
포인터를 선언할 때의 * 연산자는 변수가 포인터라는 것을 알려주는 역할이다.
포인터를 역참조할 때의 * 연산자는 포인터의 메모리 주소를 역참조하겠다는 것을 알려주는 역할이다.

int *ptr;				// 포인터 선언할때의 * 연산자
printf("%d\n", *ptr);	// 포인터를 역참조할 때의 * 연산자

역참조로 주소에 접근하여 값을 저장하는 것이 가능하다.

#include <iostream>

using namespace std;

int main() {
    int num = 10;
    int *ptr = &num;

    printf("num: %d\n", num);
    printf("&num: %#x\n", &num);
    printf("ptr: %#x\n", ptr);
    printf("&ptr: %#x\n", &ptr);
    printf("*ptr: %d\n", *ptr);

    *ptr = 20;  // 역참조로 주소에 접근하여 값을 변경
    printf("*ptr: %d\n", *ptr);

    return 0;
}

포인터 변수의 주소값이 가리키는 값을 변경하면 일반 변수 num의 값이 변경된다.

8.2 이중 포인터

📌 이중 포인터

#include <iostream>

using namespace std;

int main() {
    int num = 10;       // 변수의 선언
    int *ptr = &num;    // 포인터의 선언, num의 메모리 주소를 포인터 변수 ptr에 저장

	printf("num: %d\n", num);		// num의 값
    printf("&num: %#x\n", &num);	// num의 주소값
    printf("ptr: %#x\n", ptr);		// ptr의 값
    printf("&ptr: %#x\n", &ptr);	// ptr의 주소값
    printf("*ptr: %d\n", *ptr);		// 역참조 연산자 * 사용
    
    int **ptr2 = &ptr;		// 이중 포인터
    
    printf("ptr2: %#x\n", ptr2);	// 이중 포인터 ptr2의 값
    printf("&ptr2: %#x\n", &ptr2);	// 이중 포인터 ptr2의 주소값
    printf("*ptr2: %#x\n", *ptr2);	// 이중 포인터 ptr2의 실제값
    printf("**ptr2: %d\n", **ptr2);	// 이중 포인터 ** 사용
    
    return 0;
}

이중 포인터 **ptr2 는 2번 참조하여 num 의 값(10)을 반환한다.

& 연산자는 포인터 ptr 이 할당된 메모리의 시작 주소(0x6dc1b0a0)를 반환한다.

포인터 ptr2 에 포인터 ptr 의 주소(0x6dc1b0a0)를 저장하였기 때문에 포인터ptr2 를 출력하면 ptr 의 주소(0x6dc1b0a0)가 출력된다.

포인터 ptr2 의 주소값을 출력하면 새로운 주소(0x6dc1b098)가 출력된다.

* 연산자를 사용하여 *ptr2 을 출력하면 포인터 ptr 의 값(0x6dc1b0a8)이 출력된다.

포인터 ptr 에는 num 변수의 주소(0x6dc1b0a8)를 저장했기 때문에 포인터 ptr 을 출력하면 num 변수의 주소(0x6dc1b0a8)가 출력된다.

* 연산자를 사용하여 출력하면 num 의 값(10)을 반환된다.

흐름: **ptr2*(*ptr2)*(ptr)*(&num)num10

8.3 포인터 연산

📌 포인터 연산

포인터는 값을 증가시키거나 감소시키는 * , / , + , - 연산이 가능하다.

+ 연산의 경우 증가되는 값은 포인터가 가리키는 객체의 크기이다.

하지만 포인터끼리의 * , / , + 은 아무런 의미가 없다.

포인터끼리의 - 연산은 두 포인터 사이의 상대적인 거리를 나타낸다.

포인터에 정수를 더하거나 뺄 수는 있지만, 실수와의 연산은 할 수 없다.

포인터끼리 대입하거나 비교할 수 있다.

포인터 연산 후 포인터가 가리키고 있는 주소는 포인터의 타입에 따라 달라진다.

다음은 포인터 증가의 예시이다.

#include <iostream>

using namespace std;

int main() {
    int num = 10;
    int *ptr = &num;

    double num2 = 0.1;
    double *ptr2 = &num2;

    printf("num: %d\n", num);
    printf("ptr: %#x\n", ptr);              // 16진수
    printf("ptr + 1: %#x\n", ptr + 1);      // 16진수
    printf("ptr: %d\n", ptr);               // 10진수
    printf("ptr + 1: %d\n", ptr + 1);       // 10진수

    printf("num2: %f\n", num2);
    printf("ptr2: %#x\n", ptr2);            // 16진수
    printf("ptr2 + 1: %#x\n", ptr2 + 1);    // 16진수
    printf("ptr2: %d\n", ptr2);             // 10진수
    printf("ptr2 + 1: %d\n", ptr2 + 1);     // 10진수

    return 0;
}

int의 경우 +1을 하면 4 byte 만큼 증가하고, double의 경우 +1을 하면 8 byte만큼 증가한다.

8.4 배열과 포인터

📌 배열과 포인터




profile
평범한 개발자

0개의 댓글