Null(프로그래밍 언어)

덤프버전 :


1. 개요
2. 상세
3. 0과의 차이점
4. 각 언어에서
5. 기타


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만을 원소로 갖는 집합, null은 공집합이다. 수리논리학으로 설명하면 안 된다.
0 = {0}, null = {}
  • 종이에 0이라는 숫자를 써보자. 0이라고 보이는 면이 0이고, 아무것도 없는 뒷면 백지부분이 Null이다.
  • 아래 그림과 같이 0은 화장실 휴지걸이에 휴지 없이 휴지심만 걸려 있는 상태지만, null은 휴지심도 걸려 있지 않은 상태다.
파일:0과 null 차이.jpg


4. 각 언어에서[편집]




C 프로그래밍에서는 '존재하지 않는 메모리 주소'를 NULL로 나타낸다. 특정 포인터 변수를 초기화할 때는 실제로 메모리를 할당하기 전에 NULL로 초기화하는 버릇을 들이자. 이런 식으로
char *ptr = NULL;
ptr = (char*)malloc(...);


포인터 변수와 관련된 연산에서 값이 0인 정수 상수식이 나오면 이를 곧 NULL로 해석한다(사실 NULL은 0, 혹은 (void*)0과 같도록 정의되어야 한다). 따라서 위의 코드는 아래와 같이 써도 된다.
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의 경우 주의할 사항이 있다.
let test = null;
console.log(test == 0); // true (1)
console.log(test === 0); // false (2)

$test = NULL;
print ( $test == 0 ) ? "true" : "false" ; // (1)
print ( $test === 0 ) ? "true" : "false" ; // (2)

위와 같이 비교하면 (1)[2]은 대충 퉁치고 넘어가는 느슨한 비교이기 때문에 true가 출력되고, (2)[3]는 변수의 자료형까지 다 비교하므로 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을 상속하는 등의 경우[4]도 가끔 있으며, 기존 NULL포인터 개념과는 약간 다른 방식으로 사용된다.

java.lang.NullPointerException 이라 하여, Java에서 뭔가를 잘못하여 Null을 참조한다거나 하는 상황에 뜨는 오류이다. Java 프로그래밍을 해보면 정말 지긋지긋하게 많이 뜨기 때문에, 프로그래머 유머로 쓰이기도 하고, 자바 파생 언어인 Kotlin의 경우도 이걸 해결하기 위해 여러가지로 많이 노력했다. 비슷한 종류의 오류로 C/C++의 Segmentation fault가 있는데, 이는 유효하지 않은 메모리값을 참조할 때 발생하는 오류료 자바의 NullPointerException과는 약간 다르지만, 이 오류가 발생하는 가장 큰 원인이 포인터 역참조 전 포인터의 값이 NULL인지 확인하지 않는 것이기 때문에 결은 비슷하다. 특히 이러한 Null 포인터 관련 오류들은 컴파일 타임에는 나타나지 않고 런타임에 잘 돌아가다가 프로그램이 죽어버리는 경우가 부지기수라 디버깅하기도 쉽지 않다.

때문에 Null 참조자 를 처음 만든 토니 호어[5]가 '10억 불짜리 실수'(billion dollar mistake)였다고 회고한 적 있다. 널 포인터를 체크하지 않고 사용해서 발생하는 버그가 엄청나게 많기 때문. 때문에 최신 언어들은 Null 참조자를 배제하려는 움직임을 보인다. 한 예로, Rust와 같은 최신 시스템 프로그래밍 언어는 불변 참조자, 소유권 등의 개념을 도입해 Null을 참조하는 코드를 컴파일 타임에 배제할 수 있도록 설계되어 있다.

5. 기타[편집]


힙합엘이에서는 어그로성 글에 이 Null 댓글을 달아주는 불문율이 있다.

5ch 프로그래머 게시판에서는 NullPointerException을 가나로 줄여 '누루포' 라고 부르는데 '누루포(ぬるぽ)'라고 하면 '각(ガッ)'이라 답하는 암묵의 룰이 있다고 한다. Steins;Gate 0에서도 나온다.

[1] 패딩(Padding)바이트라고 한다[2] '='이 2개[3] '='이 3개[4]
Object.create(null)
처럼 null을 프로토타입으로 사용하는 경우 등
[5] Tony Hoare. Quick sort를 발명한 사람이다.

파일:CC-white.svg 이 문서의 내용 중 전체 또는 일부는
문서의 r130 판{{{#!wiki style="display: inline; display: 1.2;"
, 1.2번 문단}}}에서 가져왔습니다. 이전 역사 보러 가기
파일:CC-white.svg 이 문서의 내용 중 전체 또는 일부는 다른 문서에서 가져왔습니다.
[ 펼치기 · 접기 ]
문서의 r130 판{{{#!wiki style="display: inline; display: 1.2;"
, 1.2번 문단}}} (이전 역사)
문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)

문서의 r 판{{{#!wiki style="display: inline; display: none;"
, 번 문단}}} (이전 역사)



파일:크리에이티브 커먼즈 라이선스__CC.png 이 문서의 내용 중 전체 또는 일부는 2023-10-19 00:44:59에 나무위키 Null(프로그래밍 언어) 문서에서 가져왔습니다.