为什么我必须将地址强制转换为整数以使其可赋值?

Why do I have to cast an address into an integer to make it assignable?

本文关键字:整数 赋值 转换 地址 为什么      更新时间:2023-10-16

指针存储在堆或堆栈上的地址。经过一番搜索,我试图理解什么是"地址";我发现它只是一个映射内存区域的整数值。

  • 我想知道:只要地址只是一个整数,为什么我不能把它赋值给一个整数变量:

    #include <iostream>
    using std::cout;
    using std::endl;
    int main()
    {
        int  a    = 1024;
        int* ptrA = &a;
        cout << "ptrA: " << ptrA << endl;   //  0018FF44
        cout << "*ptrA: " << *ptrA << endl; //  1024
        cout << "&a: " << &a << endl;       //  0018FF44
        cout << "a: " << a << endl;         //  1024
    //  int b = ptrA;      // why this is incorrect
        int b = (int)ptrA; // why I need this?
        cout << "b: " << std::hex << b << endl; //  18FF44
        // so b is identic to ptrA!
        std::cout << std::endl;
        return 0;
    }
    

主要有两个原因。

  1. int可能不够大,无法存储指针值。这是特定于实现的细节。在64位平台上使用64位内存地址的c++实现仍然很常见,其中int只有32位。

  2. 类型安全。存在不同类型的原因之一是为了让编译器捕捉明显的错误,例如使用指向一个类的指针,而期望使用指向另一个类的指针。如果指向每个对象的所有指针都是普通的int型,则这些错误将不会被捕获。

我发现它只是一个整数值,这是内存的映射方式。

通常是正确的,但是不一定是正确的。

c++标准允许许多有问题的东西,比如eg。变量中不用于存储值的位,无效且可能导致崩溃的特定值,等等。指针和整型在这些点上可能不同。

其中一部分是在常用平台上的实际问题:int和指针可以有不同的大小(例如;4和8字节)。

我想知道:只要地址只是一个整数,为什么我不能赋值它是一个整型变量

…这就是为什么你不能这样做:不能保证在内存中赋值是可能的和/或有意义的。

在类似x86的平台上,只要使用正确的int大小,就不会有真正的问题,但是c++不仅仅是x86…

可以,但只适用于大到足以容纳指针值的整型。在64位系统上,指针有64位长,而int通常只有32位。虽然您可以使用long intlong long int(取决于哪种处理器和哪种操作系统),但也可以使用inttypes.h类型的intptr_t,它可以保证能够保存指针的值。

但是,请注意,几乎不应该将指针的值放入整型变量中。

来自C语言标准ISO/IEC9899§6.3.2.3/p6指针:

任何指针类型都可以转换为整型。除先前指定的结果是实现定义的。如果结果不能以整数类型表示,行为为未定义的。结果不需要在任何的值范围内整数类型。

如标准所述,在将指针转换为整数时存在某些问题。

  1. 结果由实现定义。
  2. 结果可能无法用整数类型表示,从而导致未定义的行为。
  3. 结果不需要在任何整数类型的值范围内。
考虑到上述原因,c++作为一种强类型语言禁止这种隐式转换,以避免意外的行为。但是,作为程序员,您知道自己在做什么,因此允许进行这种显式转换。

类型由它使用的数据表示定义由可应用于它的操作定义。"地址只是一个整数"是关于数据表示的,而不是关于操作的。地址不是整数

c++是一种强类型语言。当然,在大多数情况下,指针的地址只是一个整数的十六进制表示,它表示内存中的一个位置。数据类型将告诉编译器需要在堆栈上节省多少空间来存储该变量。在32位机器上,指针通常为4字节。

至于转换,这只是语言是如何被创造出来的。指针最初只能指向同类型变量的位置。唯一的例外是void

对于使用强制类型转换的转换,上面已经提到过,c++是强类型语言,必须知道它处理的是什么类型