본문 바로가기

프로그래밍 언어 정리/C, C++

[C++] NULL과 nullptr

NULL과 0은 다릅니다. NULL은 포인터이고 0은 int이니 사실은 비교도 되지 않습니다.
NULL과 NOT NULL로 나뉘고, 0은 그저 NOT NULL에 불과합니다.

 


[NULL]

 

초기화조차 안 한 상태. 포인터 변수에 넣어서 0 주소를 넣는 용도로 사용할 수도 있지만 일반 변수에도 넣을 수 있습니다.

분명 위에서 NULL은 포인터라고 했는데 일반 변수에 들어간다니 조금 의아합니다. 아래에서 확인해 봅시다.

 

#include <iostream>

using namespace std;

int main(void) {
    int a = NULL; // 가능
    int* b = NULL; // 가능
    
    cout << a << '\n'; // 0
    cout << b << '\n'; // 0

    return 0;
}

 

위 코드를 실행하면 오류 없이 둘 다 0을 출력합니다.

 

 

더 정확한 확인을 위해 함수를 사용해 보고 주소를 찍어보겠습니다.

 

#include <iostream>

using namespace std;

void test(int n) {
    cout << "나는 안포인터\n";
}

void test(int *n) {
    cout << "나는 포인터\n";
}

int main(void) {
    int a = NULL;
    int* b = NULL;

    test(a); // 나는 안포인터
    test(b); // 나는 포인터
    
    cout << &a << '\n'; // 주소값 있음
    cout << b << '\n'; // 주소값 없음 (NULL: 0x00)

    return 0;
}

 

분명 위에서 NULL과 0은 다르다고 했었고, NULL은 포인터이니 int에 들어가지도 못해야 합니다.

그러나 int로 선언한 a에 NULL을 넣었음에도 오류 없이 0이라는 값이 들어갔습니다. 주소도 0x00을 가리키지 않습니다.

초기화하지 않은 정수형 변수에 기본적으로 0이 들어가는 것과 같은 모습입니다.

 

포인터형인 b에 NULL을 넣어 정상적으로 작동한 것과는 반대로 a의 결과는 이해할 수 없습니다.

아래에서 하나의 코드를 더 보겠습니다.

 

 

#include <iostream>

using namespace std;

void test(int n) {
    cout << "나는 안포인터\n";
}

void test(int *n) {
    cout << "나는 포인터\n";
}

int main(void) {
    test(NULL);
  
    return 0;
}​

 

test(NULL)이 오버로딩된 두 함수에 둘 다 들어갈 수 있다는 이유로 위의 코드는 오류를 일으킵니다.

여기까지의 결과로 우리는 NULL이 포인터가 아닌 타입의 초기화(0, NUL문자)포인터의 초기화(NULL)를 둘 다 할 수 있다는 것을 알 수 있습니다.

 


[nullptr]

 

위의 문제를 해결하기 위해 nullptr을 사용합니다.

 

#include <iostream>

using namespace std;

void test(int n) {
    cout << "나는 안포인터\n";
}

void test(int *n) {
    cout << "나는 포인터\n";
}

int main(void) {
    int a = nullptr; // 불가능
    int* b = nullptr; // 가능

    test(b); // 나는 포인터
    test(nullptr); // 나는 포인터

    return 0;
}

 

위와 같이 nullptr을 사용하면 포인터가 아닌 타입에 대입이 불가능합니다.

또한 인자로 직접 nullptr을 넘겨줘도 바로 포인터로 인식하였습니다.

 

NULL의 모호함을 nullptr을 사용하여 해결할 수 있습니다.

포인터를 초기화할 때는 nullptr을 사용하는 것을 권장합니다.

 

 

※ 그렇다고 일반 변수에 NULL을 넣어서 초기화하면 안됩니다.