将指针类型转换为int会崩溃

typecasting a pointer to an int crashes

本文关键字:崩溃 int 指针 类型转换      更新时间:2023-10-16

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

int i1=12;
int *p1=&i1;
cout<<*(*((int***)&p1)); cout<<"nn           "; //is same
cout<<*(int*)*(int*)&p1; cout<<"n           "; //is same

当第二条语句有效地与i1的打印值相同时,为什么它会崩溃。

不能像这样假装指针和整数是一样的。您的代码对类型宽度和对齐方式进行了大量假设,使用错误的类型进行混叠,然后取消引用所有都有未定义的行为。如果它在你"幸运"之前就"奏效"了。

把它扔掉,按照C++语言的语义写一些有意义的东西。

您的假设完全错误,一个正常的编译器会警告您:

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))取消引用结果指针,使其成为内部

你对演员阵容做了什么:

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

(int*)&p1!优步!现在编译器必须将您的指针对指针视为指向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位机器上,你写的代码也很好,但是未定义的行为,还会导致编译器警告。

希望能有所帮助:-)