1. 메모리와 주소

1
2
// 정수는 4byte
int i;

C++에서 변수를 만들면 변수에 메모리 주소를 할당(예약)한다.

이 때, 변수 i의 메모리 주소는 변수가 사용하는 메모리 주소 첫번째를 가리킨다.

  • &(ampersand,앰퍼샌드) 연산자로 메모리 주소를 얻을 수 있다.

2. 포인터

  • 자바, 파이썬, 자바스크립트는 개발자가 직접 변수에 메모리를 할당하거나 해제할 수 없고 GC를 통해 이를 수행한다.
  • C, C++ 하위레벨 언어는 GC가 없는 대신, 개발자가 직접 필요한 메모리를 예약 및 해제할 수 있다.

포인터란, 변수의 메모리 주소를 담는 타입이다.

  • 메모리 동적할당
  • 데이터 복사하지 않고 매개변수로 사용
  • 클래스 및 구조체 연결

ex) 연결리스트의 노드

1
2
3
4
5
6
7
8
9
10
11
12
#include<bits/stdc++.h>
using namespace std;
int i;
string s = "kundol";
int main(){
i = 0;
int * a = & i;
cout << a << '\n';
string * b = &s;
cout << b << '\n';
return 0;
}
  • & i : 변수의 메모리 주소
  • “타입 * 형태” 로 포인터를 정의한다.

포인터의 크기

  • OS가 32bit라면 4byte, 64bit라면 8byte로 고정
  • 어떤 타입(string,int, char 등) 상관없이 무조건 위 수치대로 고정
  • 포인터는 메모리 주소를 담는 것이지 변수 자체를 담는 것이 아니다.
    • 집 주소(포인터)의 크기와 집(메모리)의 크기는 상관이 없다!

ex) 1byte 짜리 char 타입의 변수의 포인터 크기는 1byte가 아니다.

3. 역참조연산자

  • (에스터리스크) 기호를 포인터와 사용하여 역참조로 해당 메모리 주소의 할당된 값을 참조할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
#include<bits/stdc++.h>
using namespace std;
int main(){
string a = "abcda";
string * b = &a;
cout << b << "\n";
cout << *b << "\n";
return 0;
/*
0x6ffdf0
abcda
*/
}
  1. a 라는 변수(메모리)에 ‘abcda’ 라는 string 값이 할당
  2. string * b 로 포인터를 정의하여 a 변수의 메모리를 할당
  3. *b 로 포인터를 역참조하여 포인터의 메모리 주소에 할당된 값을 출력

4. array to pointer decay

배열을 변수에 할당하여 해당 변수(주소값)을 T * 라는 포인터에 할당하게 되면, T[N] 이라는 배열의 크기 정보 N이 없어지고 첫번째 요소의 주소가 바인딩되는 현상

1
2
3
4
5
6
7
8
9
10
11
#include<bits/stdc++.h>
using namespace std;
int a[3] = {1, 2, 3};
int main(){
int * c = a;
cout << c << "\n";
cout << &a[0] << "\n";
cout << c + 1 << "\n";
cout << &a[1] << "\n";
return 0;
}
  1. vector(동적배열)은 안되고 array(정적배열)만 가능
  2. int * c 포인터에 a array를 할당
    1. array to pointer decay 현상 발생
  3. c 를 출력하면 array의 첫번째 요소의 메모리 주소가 출력 (c == &a[0])
  4. 포인터 c에 1을 더하면 array의 두번째 요소를 의미한다.