1. 개요
화면상에는 표시되지 않고 오직 바이트상으로만 존재하는 제어 문자 가운데 하나.아스키 코드 0번(0x00). Null은 문자 '0'과는 다르며 문자 '0'의 아스키 코드값은 48이다.
유니코드는 U+0000
텍스트 문자:
Windows 한정으로, 일반적인 텍스트 편집기에서는 고정 폭 글꼴을 쓰는 경우에 한해서 공백 비슷하게 표시되는 경우가 있다.
2. 상세
텍스트를 입력하는 필드 같은데서 바이트 수가 정해져 있는데, 그 바이트 수를 채우지 못하고 끝내버리면 오류가 발생할 수도 있다. 이런 경우에 바이트 수를 임의로 채우기 위해 나머지 자리에 Null 문자를 넣는다.[1] 예를 들면 MP3 파일에 사용되는 ID3 태그 같은 것들이 있다. 일부 프로그램은 Null 문자가 아닌 공백 문자(0x20)를 대신 입력하는 경우도 있다. FAT 파일 시스템에서도 공백으로 채운다. 예를 들면 ABCDEFG.TXT라는 파일은ABCDEFG .TXT
와 같이 기록된다.3. 0과의 차이점
개념적으로는 [math(0)]은 숫자로 정의되었는데 내용이 없는 것, Null은 숫자인지 글인지 정의된 형식조차 없는 것이다.수학의 셈 측돗값일 경우 0은 Null과 같고, 어원상으로 봤을 때도 독일어 Null이 0을 의미한다.
이해하기 어렵다면 다음과 같은 비유들이 도움이 된다.
- 학생 때 배운 수준의 집합 개념으로 비유해 보면,
- 종이에 0이라는 숫자를 써보자. 0이라고 보이는 면이 0이고, 아무것도 없는 뒷면 백지 부분이 Null이다.
- 수능 등의 시험에서 0은 시험에 응시했으나, 원점수가 0점인 경우이나, Null은 결시 또는 무효 처리된 경우이다. 전자는 표준 점수와 등급이 나오지만, 후자는 애초에 점수 정보가 없는 것으로 간주된다.
- 좌표평면에 y = 0이라는 그래프가 존재하면, 모든 x에 대해 y값은 0이지만, 아예 그래프 조차 존재 하지 않으면 Null이다.
- 아래 그림과 같이 휴지가 다 떨어진 건 똑같지만, 0은 화장실 휴지걸이에 휴지는 없이 휴지심만 걸려 있는 상태고, Null은 휴지심도 걸려 있지 않은 상태다.
링크
4. 각 언어에서
프로그래밍 언어 문법 | ||
{{{#!wiki style="margin: -16px -11px; word-break: keep-all" | <colbgcolor=#0095c7><colcolor=#fff,#000> 언어 문법 | C(포인터 · 구조체 · size_t) · C++(자료형 · 클래스 · 이름공간 · 상수 표현식 · 특성) · C# · Java · Python(함수 · 모듈) · Kotlin · MATLAB · SQL · PHP · JavaScript · Haskell(모나드) |
마크업 문법 | HTML · CSS | |
개념과 용어 | 함수(인라인 함수 · 고차 함수 · 람다식) · 리터럴 · 상속 · 예외 · 조건문 · 참조에 의한 호출 · eval | |
기타 | == · === · deprecated · NaN · null · undefined · 배커스-나우르 표기법 | |
프로그래밍 언어 예제 · 목록 · 분류 | }}} |
C 프로그래밍에서는 '존재하지 않는 메모리 주소'를 NULL로 나타낸다.[2] 특정 포인터 변수를 초기화할 때는 실제로 메모리를 할당하기 전에 NULL로 초기화하는 버릇을 들이자. 이런 식으로
#!syntax cpp
char *ptr = NULL;
ptr = (char*)malloc(...);
포인터 변수와 관련된 연산에서 값이 0인 정수 상수식이 나오면 이를 곧 NULL로 해석한다(사실 NULL은 0, 혹은 (void*)0과 같도록 정의되어야 한다). 따라서 위의 코드는 아래와 같이 써도 된다.
#!syntax cpp
char *ptr = 0;
ptr = (char*)malloc(...);
흔히 ASCII나 유니코드상에서 NULL의 문잣값이 0이라 메모리 주소로 사용할 때의 NULL도 0일 거라고 생각하고 코딩을 하는 경우가 있는데 위험하다. C 표준은 코드상에 직접 나타나는 0에 NULL이란 의미를 부여하고 있지만, 내부적으로 실제로 NULL값이 뭐가 되는지는 규정하지 못한다. 이는 프로그램이 컴파일되는 시스템이 결정하며, 따라서 NULL != 0x0인 경우가 있다. 이런 예에서는 위의 char *ptr = 0;이란 코드가 실제로 ptr에 주솟값 0x0을 대입하지 않는다. 애당초 그 코드 자체가 '시스템에 정의된 NULL 값을 대입한다'는 의미지 0x0을 대입한다는 의미가 아니니까.
하지만 워낙 많은 시스템에서 NULL을 0으로 정의하고 있었고, 오래전부터 내려온 코드들에 대해 호환성을 가지기 위해 개발 환경이 맞춰지다 보니 이제는 0이 아닌 환경을 생각도 하기 힘들어졌다. null이 정의되지 않은 언어(Solidity 등)조차도 null값이 필요한 상황은 0으로 사용할 정도.
다만 코드의 구체성을 높이기 위해서 0과 Null을 다르게 만드는 프로그래밍 언어도 있다. Java, JavaScript, PHP에서는 Null은 Null이지 0으로 대체할 수 없다. 단, JavaScript와 PHP의 경우 주의할 사항이 있다.
#!syntax javascript
let test = null;
console.log(test == 0); // true (1)
console.log(test === 0); // false (2)
#!syntax php
$test = NULL;
print ( $test == 0 ) ? "true" : "false" ; // (1)
print ( $test === 0 ) ? "true" : "false" ; // (2)
위와 같이 비교하면 (1)[3]은 대충 퉁치고 넘어가는 느슨한 비교이기 때문에 true가 출력되고, (2)[4]는 변수의 자료형까지 다 비교하므로 false가 출력된다. PHP 이외에도 이와 유사한 형태로 비교 연산자를 분리한 언어에서는 이와 유사한 식으로 인식한다.
null 대신 nil을 쓰는 경우도 있다. 대표적인 것이 LISP, 이 언어는 데이터 단위가 리스트인지라 false의 의미도 겸한다. Go 언어 및 Lua 역시 nil을 사용한다. (Python의 경우는, null과 비슷한 값으로 None이라는 값을 사용하며, Lingo의 경우 null대신 VOID를 사용한다)
Objective-C에서는 NULL, nil, NIL 모두 기술적으론 똑같이 (void *0)이긴 하지만 혼용해서는 안 된다. NULL은 고전적인 C 널 포인터, NIL은 클래스 널 포인터, nil은 인스턴스 널 포인터로 서로 역할이 나뉘어져 있다. 혼용하면 여러 가지 의미로 지옥을 맛보게 된다.(…) 이 때문인지 Objective-C의 후계로 Apple에서 개발한 Swift에서는 이 면을 대폭 변경했다. 이와 관련해서는 Apple 공식 개발자 지원 문서를 확인 바람.
JavaScript의 경우에는, null과 undefined, NaN등을 모두 사용할 수 있어 혼용하기 쉽지만, 여기서 null은 특별히 '의도적으로 비워둔 값' 이라는 의미로 사용되는 경우가 많다. 다만 자바스크립트에서도 null을 상속하는 등의 경우[5]도 가끔 있으며, 기존 NULL포인터 개념과는 약간 다른 방식으로 사용된다.
java.lang.NullPointerException이라 하여, Java에서 뭔가를 잘못하여 Null을 참조한다거나 하는 상황에 뜨는 오류가 있다. Java 프로그래밍을 해보면 정말 지긋지긋하게 많이 뜨기 때문에, 프로그래머 유머로 쓰이기도 하고, 자바 파생 언어인 Kotlin의 경우도 이걸 해결하기 위해 여러 가지로 많이 노력했다. 비슷한 종류의 오류로 C/C++의 Segmentation fault가 있는데, 이는 유효하지 않은 메모리값을 참조할 때 발생하는 오류로 자바의 NullPointerException과는 약간 다르지만, 이 오류가 발생하는 가장 큰 원인이 포인터 역참조 전 포인터의 값이 NULL인지 확인하지 않는 것이기 때문에 결은 비슷하다. 특히 이러한 Null 포인터 관련 오류들은 컴파일 타임에는 나타나지 않고 런타임에 잘 돌아가다가 갑자기 나타나 프로그램이 죽어버리는 경우가 부지기수라 디버깅하기도 쉽지 않다. 이를 위해 8버전부터 Optional을 제공하고는 있지만, 기존 7버전까지의 자바 기본 메서드는 NPE에서 자유롭지 못하다. 이를 위해 유저가 필요한 기능을 직접 Optional로 감싸주는 메서드를 만들어야하는 불편함이 있다.
때문에 Null 참조자를 처음 만든 토니 호어[6]가 '10억 불짜리 실수'(billion dollar mistake)였다고 회고한 적 있다. 널 포인터를 체크하지 않고 사용해서 발생하는 버그가 엄청나게 많기 때문. 때문에 최신 언어들은 Null 참조자를 배제하려는 움직임을 보인다. 한 예로, Rust와 같은 최신 시스템 프로그래밍 언어는 불변 참조자, 소유권 등의 개념을 도입해 Null을 참조하는 코드를 컴파일 타임에 배제할 수 있도록 설계되어 있다.
5. 기타
힙합엘이에서는 어그로성 글에 이 Null 댓글을 달아주는 불문율이 있다.5ch 프로그래머 게시판에서는 NullPointerException을 가나로 줄여 '누루포'라고 부르는데 '누루포(ぬるぽ)'라고 하면 '각(ガッ)'이라 답하는 암묵의 룰이 있다고 한다. Steins;Gate에도 나온다.
2018년 초 Joseph Tartaro라는 인물에 벌금 30달러에 불만을 가지고 차량 번호판을 Null로 설정[7]하여 꼼수를 부려보고자 했으나 오히려 12,049 달러(2024년 7월 기준 약 1,680만 원)의 벌금 폭탄이 내려왔다. 이유는 경찰관이 간혹 번호판을 공란으로 입력하는데 이때 SQL 데이터베이스 기본값이 NULL로 지정되어 있고 이것이 문자열로 인식되어 NULL이라는 번호판 소유자에게 벌금을 매긴다로 여겨졌기 때문이다. The Verge 기사
[1] 패딩(padding) 바이트라고 한다[2] C++에서는 추후에 nullptr이 추가되어 주소에 관해서는 nullptr로 초기화 혹은 이미 있는 변수라면 대입을 한다.[3] '='이 2개[4] '='이 3개[5]
Object.create(null)
처럼 null을 프로토타입으로 사용하는 경우 등[6] Tony Hoare. Quick sort를 발명한 사람이다.[7] 실제로 Christopher Null이라는 인물이 있어 딱히 이상할 것은 없다. Christopher Null 위키백과 문서(영어)