널 포인터 (Null pointer) 본문
Null values and Null pointers
일반 변수와 마찬가지로 포인터는 인스턴스화 될 때 초기화되지 않는다.
값이 할당되지 않으면 포인터는 기본적으로 어떤 쓰레기 주소를 가리킨다.
포인터의 위험성 중 쓰레기 주소 값이 들어간 경우, de-referencing을 시도하게 되면
실제 메모리에 데이터가 잘 담겨있는 것이 아니라서, 엉뚱한 곳에 가서 데이터를 찾기 때문에
OS가 문제가 있다고 경고한다고 앞 포스팅에서 말씀드렸다.
이런 문제를 방지하기 위해서 null pointer라는 것을 사용한다.
메모리 주소 외에도 포인터가 저장할 수 있는 값이 하나 있다. 바로 null 값이다.
null 값은 포인터가 아무것도 가리키지 않는다는 것을 의미하는 특수 값이다.
null값을 가진 포인터를 null pointer라고 한다.
null pointer 사용법
C-style에서는 포인터로 null 값을 지정하려면 선언할 때 0을 넣어준다.
이렇게 NULL을 넣어주기도 한다.
그리고 최근에 Modern C++ Style로는 nullptr 이라는 것이 있다.
어떻게 작동하냐면
nullptr이 아닐 경우에만 ptr이 의미가 있기 때문에 쓸모있는 작업을 하라고 하는 거고
nullptr이 들어왔으면 이 포인터 값이 제대로 들어온 주소가 아니니까 아무것도 하지 말아라 하는 용도로 쓰인다.
초기화하는 방법은 다른 변수와 같다.
또는
0도 많이 쓰였지만 앞으로는 nullptr 쓰는 게 좋을 것 같다.
값 0은 포인터 유형이 아니므로 포인터가 null 포인터임을 나타내기 위해서 포인터에 0을 할당하는 것은 일관성이 없다.
드문 경우이지만, 리터럴 0을 사용할 경우 컴파일러에서 null 포인터를 의미하는지 정수 0을 의미하는지 확인할 수 없으므로 문제가 발생할 수 있다.
doSomething(0);
이러한 문제를 해결하기 위해 C++11 에서는 nullptr이라는 새로운 키워드를 도입했다.
nullptr은 true, false와 같은 불린 키워드와 마찬가지로 키워드 및 r-value 상수이다.
int *ptr{ nullptr }; //ptr is still an integer pointer, just set to a null value
C++은 암시적으로 nullptr을 포인터 모든 유형으로 변환한다.
따라서 위의 예제에서 nullptr은 암시적으로 정수 포인터로 변환된 다음, nullptr 값이 ptr에 할당된다.
이것은 정수 포인터 ptr을 널 포인터로 만드는 효과가 있다.
nullptr 리터럴로 함수를 호출하는 데에도 사용할 수 있다.
함수 파라미터로 넘어갈 때 유용하다.
함수를 만들고
변수에 주소를 직접 넣어도 잘 작동하고,
포인터 변수에다가 d의 주소를 넣고 그 ptr을 넣어줘도 잘 작동하는 것을 볼 수 있다.
C++11 에서는 nullptr을 사용해서 포인터를 null 값으로 초기화하자.
std::nullptr_t in C++ 11
C++은 <cstddef> 헤더에 있는 std::nullptr_t라는 새로운 유형을 도입했다.
nullptr_t에 뒤에 붙은 _t는 type이라는 의미다.
std::nullptr_t는 nullptr 하나의 값만 가질 수 있다.
이것은 nullptr 인자를 받아들이는 함수를 작성할 때
std::nullptr_t 타입의 매개 변수를 만들어서 쓸 수 있다.
포인터 변수의 주소를 찍어보면 어떻게 나올까?
그럼 이 포인터 변수의 주소를 찍어보자
지난 포스팅에서
이 파라미터로 넘어오는 변수는 다시 선언이 되고,
거기에 argument로 들어온 변수에 들어있는 값이 복사가 되는 것이라고 말씀드렸다.
그래서 함수에 있는 double *ptr은
main에 있는 ptr과는 다른 메모리를 쓰는 것이다.
포인터도 결국 변수이고, 함수로 넘어오면서 메모리값이 다시 복사가 되는 것이다.
nullptr 값이 다시 복사가 되고,
double d가 정의가 되어있는 메모리의 주소 값이 값 자체가 다시 복사가 된다는 또 다른 증거다.
알아두면 도움되니까 잘 알아두자.
'💘 C++ > 행렬, 문자열, 포인터, 참조' 카테고리의 다른 글
포인터의 연산과 배열 인덱싱 (Pointer Arithmetic and Array Indexing) (0) | 2022.07.10 |
---|---|
포인터와 정적 배열 (Pointer and Fixed Array) (0) | 2022.07.09 |
포인터 소개 및 기본적인 사용법 Introduction to Pointer (0) | 2022.07.07 |
C언어 스타일의 배열 문자열 C-style strings (0) | 2022.07.06 |
정적 다차원 배열 Multidimensional Arrays (0) | 2022.07.05 |