【问题标题】:Is pointer just an integer?指针只是一个整数吗?
【发布时间】:2015-01-27 18:30:13
【问题描述】:

如果我知道一个数据对象的地址,我是否可以将地址存储为整数并将该整数作为指针进行操作?

例如,

void main(){
    long a = 101010;
    long *p = &a;
    long b = p;
    printf("%lld\n", *(long*)b);
}

它总是安全的吗?

评论:long b = p; 产生警告:

Initialization makes integer from pointer without a cast

但是,程序会打印101010

【问题讨论】:

  • 语言标准中没有规定指针始终可以转换为整数。这只是一个巧合,就像 int 出于某种原因现在很久了。
  • 这段代码应该会产生一个关于使用指针作为整数而不进行强制转换的警告。
  • 如果您将此代码放在文件中并对其进行编译(启用警告),编译器会将代码标记为不正确。那么就没有必要问这个问题了
  • 没有什么是总是安全的;当然,指针不只是integer,但它始终可以表示为integer(它可能是intlong,甚至是30位值,但你可以声明这是一个integer)。
  • 在非线性寻址架构(例如 x86 实模式)中,指针甚至可能不是单个数字。例如(再次)在 x86 实模式下,所谓的“FAR”指针是段地址和段内偏移量的组合。

标签: c++ c pointers integer


【解决方案1】:

标准不能保证这样的演员阵容总是有效的。

要将指针存储为整数类型,请使用intptr_t(或其无符号表亲uintptr_t)。保证将 void * 指针转换为此类类型并转换回来,得到相同的值。

请注意,这些类型是可选的。

【讨论】:

  • 它们通常与ptrdiff_t(已签名)和size_t(未签名)相同,对吗?
  • @technosaurus Not really。另请注意,ptrdiff_tsize_t 不是可选的。
【解决方案2】:

sizeof(long) 通常由编译器定义(受制于底层硬件架构)。

sizeof(long*) 取决于您平台上虚拟内存地址空间的大小。

例如,对于 64 位操作系统和基于 x64 的处理器的 Visual Studio 编译器:

  • sizeof(long) == 4
  • sizeof(long*) == 8

因此:

  • 使用long b = p,只有p 的4 个最低有效字节被复制到b
  • 使用*(long*)b,您可能会尝试访问无效的内存地址

在本例中,如果p 的 4 个最高有效字节为零,则“无害”。但是既然不能保证是这样,当sizeof(long) != sizeof(long*)这段代码一般是不安全的。

除此之外,即使sizeof(long) == sizeof(long*),您仍应避免使用这种类型的转换(指针到整数),以使您的代码可移植到其他平台。


更新

请注意printf("%lld\n", *(long*)b) 也是不安全的。

您基本上应该使用"%ld" 来表示long 值和"%lld" 来表示long long 值。

如果sizeof(long) < sizeof(long long),则可能会导致运行时内存访问冲突。

【讨论】:

    【解决方案3】:

    即使p值和b值相同,也只有p可以访问a,即可以指向ab不能指向a。因为p 被声明为指针。 b 被声明为变量。

    您无法通过b 访问a。那么你的问题如何适合。在b 中,a 的地址仅被视为value 而不是address,因为b 是变量而不是指针..

    即使它打印101010,这个程序也不是通用的。

    【讨论】:

      【解决方案4】:

      为了安全,我们应该认为它不安全

      n 位系统上的指针大小为n 位。例如,在任何 64 位架构/编译器上,指针的大小都应该是 8 字节。这是有保证的。

      但是,数据类型没有这样的保证。它严重依赖编译器。在您的情况下,两者恰好具有相同的大小,这就是它起作用的原因。


      编辑:

      警告

      Initialization makes integer from pointer without a cast
      

      您的编译器非常适合产生警告。请检查数据类型。 int * 变量等于 int 变量。在您的情况下,它之所以有效,只是因为您的特定情况/实施中的长度相同。

      【讨论】:

        【解决方案5】:

        指针是一个变量,它的值是另一个变量的地址。像任何变量或常量一样,您必须先声明一个指针,然后才能使用它。指针变量声明的一般形式是:

        type *var-name;
        

        所有指针的值的实际数据类型,无论是整数、浮点数、字符还是其他,都是一样的,一个长的十六进制数,代表一个内存地址。不同数据类型的指针唯一的区别就是指针所指向的变量或常量的数据类型。

        指针通常具有固定大小,例如。在 32 位可执行文件上,它们通常是 32 位的。有一些例外,比如在旧的 16 位窗口上,当您必须区分 32 位指针和 16 位指针时......通常可以很安全地假设它们在现代桌面操作系统上的给定可执行文件中是统一的.

        【讨论】:

        • 转换为保证大小相同的类型非常容易......
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-31
        • 1970-01-01
        • 1970-01-01
        • 2021-03-31
        • 1970-01-01
        相关资源
        最近更新 更多