2012-04-15 2 views
7

인터뷰에서이 코드를 발견했습니다."ptr을 ptr로"ptr을 명시 적으로 캐스팅합니다.

int main() 
{ 
    int **p; 
    p = (int **) new int(7); 
    cout<<*p; 
    return 0; 
} 

* p에서 런타임 오류가 예상됩니다. 그러나 코드를 실행하면 "0x7"출력으로 성공적으로 실행됩니다. 누군가가 어떻게 작동하는지 설명해 주시겠습니까? 감사.

+1

무엇을하려하십니까? 엄지 손가락의 기본 규칙은 당신이 캐스팅해야한다면, 당신이 잘못하고 있다는 것입니다. 'new int (7)'이'int *'를 돌려주기 때문에, 당신은 캐스팅해야했습니다. 그러나 형 변환은 코드를 올바르게 만들지 못합니다. 당신이 틀렸다고 사실을 기록한 것뿐입니다. 캐스트를 제거하고 거기에서 작업하십시오. –

+0

@ Davidid : 코드는 아마도 인터뷰에서 나온 것이지 OP에서 나온 것이 아닙니다. – Vlad

+0

@ David Heffernan : 이것은 필기 시험의 면접 질문입니다. 4 개의 옵션으로 컴파일 타임 오류, 런타임 오류, 코드가 정상적으로 실행되며 위에 해당하지 않습니다. 그러한 인터뷰 질문으로 어떤 종류의 지식을 얻으려고하는지 이해하지 못합니다. – CppLearner

답변

5

여분의 제약 사항이없는 한 정답은 입니다. 위의 내용 중 하나가 아닙니다.입니다. 기본적으로 코드는 int을 할당하고 해당 메모리를 int* (마치 reinterpret_cast) 인 것처럼 해석합니다. 첫 번째 문제는 reinterpret_cast되고, 결과는 일반적인 경우에 지정되지 않은이며, int의 크기가 int*의 크기보다 작은 경우 결과는 당신이로 정의되지 않은 동작입니다 (64 비트 아키텍처를 생각한다)이다 new 호출에 할당 된 크기 이상으로 읽는 것.

+0

int (32 비트)를 int * (64 비트)로 변환하면 결과가 64 비트로 확장됩니다. – gulyan

+0

@gulyan 그러나이 경우 컴파일러는 그런 종류의 캐스트를 수행해야한다는 것을 모릅니다. 일어나는 유일한 캐스트는 위의 줄에서 int *에서 int **까지입니다! –

+1

@gulyan : 아니요, 32 비트 정수에서 64 비트 정수까지'static_cast'에서 컴파일러는 크기를 확장하는 변환을 수행 할 것입니다. 그러나'reinterpret_cast'에서 코드는 * 메모리를 재 해석한다. 즉, 그것은'int'에 포인터를 가져다가 다음 64 비트 (8 바이트)를'int * '처럼 읽습니다. 이것은 정의되지 않은 동작입니다. C 스타일 캐스트의 가장 큰 문제점 중 하나입니다. 명시 적 C++ 캐스트만큼 명확하지 않습니다. –

4

당신은 새로운 INT를 생성하고 값 7

포인터로 캐스트가보다
int *x = new int(7); 

당신을 (예를 들어, 메모리 주소 (7)에는 0x07)

int **p = (int**) new int(7); 

그런 다음이 주소를 표시와 함께 초기화 한마디.

*p is equal to (int*)7 

그것은 제

+2

이것은 코드가 정확한지, 아니면 적어도 모든 상황에서 동일한 출력을 생성하는지, 그렇지 않은지를 나타내는 것 같습니다. 'p'의 역 참조는 정의되지 않은 행동을 일으킨다. –

0
new int(7); 

그 값 7이며 포인터를 리턴하는 int 메모리를 할당 포인터 값이다.

int **p = (int **) new int(7); 

은 해당 메모리를 int**으로 해석하도록 지시합니다.

cout << *p; 

어드레스 *p에서 int * 출력하는 값이다 컴파일러 말한다. 값은 0x07입니다. (주소로 7을 처리합니다). 추가 참조가 발생하면 충돌이 발생합니다 (정확하게는 정의되지 않은 동작).

+3

코드가 이미 정의되지 않은 동작이므로 ... 추가 역 참조를 수행 할 필요가 없습니다. –

+0

@Luchian Grigore : 고마워. 도움이된다 – CppLearner

0
int main() 
{ 
    int **p;     // declare pointer to pointer called p 
    p = (int **) new int(7); // new allocates integer initialized to value of 7 and returns a pointer. Cast the pointer to a point to pointer. p now represents a pointer to a pointer with contents of 0x7. If you called **p you would get the contents at address 0x7. 
    cout << *p; // dereference p, this yields a pointer, which is an int of value 0x7. 
} 

이 질문은 귀하의 포인터 지식을 테스트 할 가능성이 가장 높지만 매우 실용적이지는 않습니다.

0
int main() 
{ 
    int **p = (int **) new int(7); 
    cout << *p; 
} 

그래서, new int(7) 메모리 sizeof(int) 바이트를 할당하고 그것에 대한 포인터를 반환한다. 메모리가 주소 X에 있다고 가정 해 봅시다. 그러면 X는 (int**)으로 캐스팅되어 p에 저장됩니다.

*p는이 어드레스로 int*X에서 int 값 7 intreprets 의미의 int** 역 참조.항상 정의되지 않은 동작에 관계없이 데이터 유형 및 임의의 reintrepretation -

  • sizeof(int*) 경우는 int*new 할당 버퍼 넘어 판독되므로 다음 읽기 sizeof(int)보다 크다.

  • 는 같은 크기 인 경우, CPU가 int*로 정수 (7)를 포함하는 메모리를 읽을 시도합니다 - 이것은 일반적으로 값 int*(7)를 얻을 것이다, 그러나 표준 5.2.10.5보고 :

제로 값으로 적분 상수 식 (expr.const)를 변환 항상 널 포인터 (conv.ptr)을 산출한다 :하지만.

일체형 또는 열거 형 값은 명시 * 는 [각주 포인터로 전환시킬 수있다 값이 0 인 다른 표현식을 변환하면 널 포인터가 필요하지 않습니다. --- end foonote] 충분한 크기의 정수로 변환 된 포인터 (구현에 그러한 포인터가있는 경우)와 같은 포인터 유형으로 되돌아 오는 포인터는 원래 값을 갖습니다. 포인터와 정수 사이의 매핑은 달리 구현 정의됩니다.

따라서 정수 값은 포인터 값 (정의되지 않음)으로 변환되지만 값은 구현 정의됩니다. 여전히 되돌릴 수있는 작업 인 것은 일 가능성이 높습니다.int 7은 값이 7 인 int*이고 결과는 "7"로 표시되는 동작을 설명합니다.

  • 포인터의 크기가 int 크기보다 작은 경우

    , 그것은 int 값의 조각을 읽고 포인터로 그 해석됩니다. 엔디안에 따라 슬라이스는 0 또는 7 또는 심지어 다른 것일 수 있지만 다시 int으로 표시되므로 포인터 값으로 변환 할 수 있어야합니다.
관련 문제