“int * ptr = int ()”값 초기화가 어떻게 불법이 아닌가?


86

다음 코드 ( 여기에서 가져옴 ) :

int* ptr = int();

Visual C ++에서 컴파일하고 포인터를 값 초기화합니다.

어떻게 가능합니까? 내 말 int()은 유형의 객체를 산출 하고 포인터에을 int할당 할 수 없음을 의미합니다 int.

위의 코드가 불법이 아닌 이유는 무엇입니까?


대답은 아니지만 좋은 질문입니다! 그런 건 본 적이 없어요.
— Josh

6
프리미티브 C에서 '생성자'을 가지고 있기 때문에 ++, int()값 구성 값 산출 int및 기본값 (나는 C ++ 03 지정된 것은 생각입니다) int입니다 0. 이것은 다음과 동일합니다.int *ptr = 0;
— wkl

7
@EmanuelEy : 아니요, 포인터가 실제로 구현되는 방식에 관계없이 0 값 정수 상수를 널 포인터 상수로 사용할 수 있습니다.
— Mike Seymour

1
@MooingDuck : NULL0이 아닌 값이 될 수 있다고 말하지 않았습니다 . 나는 그것이 0 값 정수 상수 (포함 int()) 일 수 있다고 말했습니다 .
— Mike Seymour 2011

5
@DanielPryden 그것은 내가 이전에 알지 못했던 "객체"라는 단어의 사용입니다.
— 푹신한

답변:


110

int()값이 0 인 상수 표현식이므로 널 포인터 상수를 생성하는 유효한 방법입니다. 궁극적으로 약간 다른 표현 일뿐입니다.int *ptr = NULL;


3
+1, 상수 표현 비트는 중요하며 상위 2 개 찬성 답변에서 누락되었습니다.
— David Rodríguez-dribeas 2011

이것이 C ++ 0x로 사라지나요?
— Neil G

@NeilG : C ++ 11에서도 동일하게 유지되지만 이제는 새 코드 nullptr대신 0또는 NULL새 코드에서 사용할 수있는 .
— Jerry Coffin 2011

2
@Nils : 코드 명확성 및 코드를 통한 의도 선언. 물론, C ++ 11에서는 추가 컴파일 시간 검사의 이점을 혼합에 던지기 때문에 이제 nullptr을 사용하고 싶습니다.
— Jamin Gray 2013

3
@Nils는 분명히 0null 포인터 상수 또는 숫자 0을 의미 할 수있는 반면 nullptrnull 포인터 상수는 분명하기 때문입니다. 또한 Jamin이 말했듯이 "추가 컴파일 시간 검사"도 있습니다. 입력하기 전에 생각하십시오.
— Miles Rout

35

때문에 int()수율 0로 교체이다 NULL. NULL자체로 정의 0C 년대와는 달리 NULL입니다 (void *) 0.

이것은 오류입니다.

int* ptr = int(5);

그리고 이것은 여전히 ​​작동합니다.

int* ptr = int(0);

0특수 상수 값이므로 포인터 값으로 처리 할 수 ​​있습니다. 수율하는 정수 표현 0등이뿐만 1 - 1아니라 널 포인터 상수로 사용할 수 있습니다.


1
또한 C의 NULL도 반드시 그런 것은 아닙니다 (void *)0. 이는 단순히 "값이 0 인 정수 상수 표현식 또는 void * 유형으로 캐스팅 된 표현식"으로 정의 된 구현입니다.
— Jerry Coffin 2011

@JerryCoffin 저는 다음 NULL과 같이 정의 된 C 컴파일러를 사용한 적이 없습니다 (void*)0. 항상 0(또는 어쩌면 0L). (하지만 C90이 (void*)0C에서 합법화되었을 때 이미 C ++를 사용하고있었습니다.)
— James Kanze

1
@JamesKanze : 우분투 11.04와 우리의 리눅스 #if !defined(__cplusplus) \n #define NULL ((void*)0) \n #else \n #define NULL (0)버전 에서 libio.h는 다음을 포함합니다 : 우분투에있는 gcc의 현재 버전은 4.5이고 우리 시스템에서는 4.0입니다.
— David Rodríguez-dribeas

5
" 0은 특수 리터럴입니다"-상수 표현식이고 특수 값 0을 갖기 때문 (1-1)입니다. 똑같이 특별하고 널 포인터 상수이기도합니다 int(). 0리터럴 이라는 사실 만으로도 충분하지만 상수 표현이되기위한 필수 조건은 아닙니다. 과 같은 strlen("")것은 특별한 값을 가지고 있지만 0상수 표현식이 아니므로 널 포인터 상수가 아닙니다.
— Steve Jessop 2011

@SteveJessop : 수정에 대해 동의합니다. 실제로 0는 0리터럴이 아닌 상수 값에 관한 것 입니다.
— Blagovest Buyukliev 2011

18

표현식 int()은 기본값으로 초기화 된 상수 정수로 평가되며 값은 0입니다.이 값은 특별합니다. NULL 상태에 대한 포인터를 초기화하는 데 사용됩니다.


2
이것은 Jerry의 대답에 존재하는 매우 중요한 세부 사항이 누락되었습니다. 표현식이 값 0을 산출하는 것으로는 충분하지 않지만 상수 표현식 이어야합니다 . 반대 예의 경우 with int f() { return 0; }, 표현식 f()은 값 0을 산출하지만 포인터를 초기화하는 데 사용할 수 없습니다.
— David Rodríguez-dribeas 2011

@ DavidRodríguez-dribeas, 가능한 가장 간단한 용어로 답을 제시하기 위해 서두르면서 그 부분을 생략했습니다. 지금 받아 들여지기를 바랍니다.
— Mark Ransom 2011

13

n3290 (C ++ 03은 유사한 텍스트 사용)에서 4.10 포인터 변환 [conv.ptr] 단락 1 (강조는 내 것임) :

1 널 포인터 상수는 0으로 평가되는 정수 유형의 정수 상수 표현식 (5.19) prvalue 또는 std :: nullptr_t 유형의 prvalue입니다. 널 포인터 상수는 포인터 유형으로 변환 될 수 있습니다. 결과는 해당 유형의 널 포인터 값이며 오브젝트 포인터 또는 함수 포인터 유형의 다른 모든 값과 구별 할 수 있습니다. 이러한 변환을 널 포인터 변환이라고합니다. [...]

int()0으로 평가되는 정수 유형의 정수 상수 표현식 prvalue이므로 포인터 유형을 초기화하는 데 사용할 수 있습니다. 보시다시피, 0는 특수한 경우에만 적분식이 아닙니다.


4

int는 객체가 아닙니다.

나는 여기서 무슨 일이 일어나고 있는지 당신이 int *가 int ()에 의해 결정된 메모리 주소를 가리 키도록 지시하고 있다고 믿습니다.

따라서 int ()가 0을 생성하면 int *는 메모리 주소 0을 가리 킵니다.


1
int()가장 확실한 것은 객체입니다.
— 궤도의 가벼운 경주

@Tomalak : 나는 그렇게 생각하지 않는다. 클래스가 아닌 유형의 일시적이며 C ++ 표준에 관한 한 객체 가 아니라고 말하는 것이 옳다고 생각 합니다. 그러나 "임시 객체"에 대한 섹션은 클래스 유형의 임시에 대해서만 신중하게 설명하기 시작하지만 나중에는 바인딩 참조에 대해 설명하고 물론 참조를에 바인딩 할 수 있습니다 int(). int i;의문의 여지없이 정의 i는 객체입니다.
— Steve Jessop 2011

@Steve : "객체"는 C ++의 저장소 영역이고 임시 저장소에는 실제로 저장소가 없다는 점에서이 문제에 대한 논쟁 만 기대할 수 있습니다. 그렇죠? 1.8 / 1은 임시를 명시 적으로 나열하지 않지만 포함하려는 의도가있는 것처럼 느껴집니다.
— 궤도의 가벼운 경주

1
@Tomalak : 예, 실제로 비 클래스 유형의 임시 파일은 참조하지 않는 한 스토리지가 필요하지 않습니다. 그래도 신경 쓰지 마세요.별로 중요하지 않습니다. "well int is not an object"라는 문장은 객체가 아니라 int유형 이기 때문에 참 입니다. int()객체를 생성 하든 rvalue 만 생성 하든 다른 사람이 말한 것에 영향을 미치지 않습니다.
— Steve Jessop 2011

@Steve : 그 정도는 논란의 여지가 없습니다. :)
— 궤도의 Lightness Races
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.