类型转换指向int崩溃的指针

时间:2016-04-18 14:12:54

标签: c++

我曾经认为cout语句指向相同的值,即使一个以十六进制打印,其他以整数格式打印。 但今天我在g ++上运行同样的命令,发现第二个语句崩溃了。

int i1=12;
int *p1=&i1;

cout<<*(*((int***)&p1)); cout<<"\n\n           "; //is same
cout<<*(int*)*(int*)&p1; cout<<"\n           "; //is same

为什么有效地将第二个语句与i1的打印值相同时会崩溃。

2 个答案:

答案 0 :(得分:6)

你不能假装指针和整数是这样的。您的代码对类型宽度和对齐做了大量假设,使用错误的类型别名化,然后解除引用。 它的所有都有未定义的行为。如果它&#34;工作&#34;在你成为幸运之前&#34;。

将它丢弃并根据C ++语言的语义编写一些有意义的东西。

答案 1 :(得分:1)

你的假设完全错了,普通的编译器警告你:

main.cpp: In function 'int main()':
main.cpp:10:32: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     std::cout<< *(int*)*(int*)&p1 <<std::endl;

并且不需要进行c式演员表演,绝对不需要错误演员:-)                                    ^

正确的代码是:

 std::cout<< *(int*)*(int**)&p1 <<std::endl;

因为指向int的指针的地址是int**

根据要求提供更多解释: - )

评估的每一步都做了什么:

  

p1是一个int *并指向你的i1

     

&p1是一个int **,因为它是指向int的指针。

     

*(&p1)取消引用指针,使其成为指向int(int *)

的指针      

*(*(&p1))取消引用生成的指针,使其成为一个int。

你对演员表演的所作所为:

  

&p1再次是指向指针(int **)

的指针的地址      

(int*)&p1!Ubs!现在编译器必须将指针指向为       指向int的指针。这是一个有效的表达,但不是很有用。

     

*(int*)&p1现在编译器将(int *)解引用为int。这是       仍然是一个有效的表达式,但存储的值不能保证与以前相同。如后面所述,您将完全放弃部分值!

     

(int*)*(int*)&p1现在告诉编译器它应该使用你的int值       作为指针。仍然没有崩溃但不再有效。见下一步:

     

*(int*)*(int*)&p1崩溃!现在,您尝试取消引用int值。       只要int可以存储一个,这是有效的(但不是正确的代码)       有效指针。但是在64位机器上,指针主要是       64位(不是必须!)和int使用       32位(通常也不是必须的!)。结果只有一半了       使用指针并指向不是有效地址,这导致了       崩溃。

使用以下代码示例在64位计算机上获取不同的指针值:

int i1=12;
int *p1=&i1;

std::cout << (int*)*(int*)&p1 << std::endl;
std::cout << (int*)*(int**)&p1 << std::endl;

在我的32位机器上,两个值都相同。在您的机器上,如果是64位,您将看到不同的值!并且第一个值不再指向有效地址。而且在我的32位机器上,编译器警告错误使用指针。你永远不应该忽略编译器警告!

在我的32位机器上,你编写的代码工作正常,但是未定义的行为也会导致编译器警告。

希望有所帮助: - )