指向C中不同数据类型的指针

Posted

技术标签:

【中文标题】指向C中不同数据类型的指针【英文标题】:Pointer to different data type in C 【发布时间】:2015-07-08 19:29:25 【问题描述】:

我已经用 C 编译并运行了以下程序:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main(int argc, char* argv[])
  uint8_t data[8] = 0, 1, 2, 3, 4, 5, 6, 7;
  uint32_t* pointer32 = &data[0];
  uint64_t* pointer64 = &data[0];

  printf("%" PRIu64 "\n", *pointer64);
  printf("%" PRIu32 "\n", *(pointer32++));
  printf("%" PRIu32 "\n", *pointer32);

  return 0;

并收到以下预期输出:

506097522914230528
50462976
117835012

输出是正确的,并且对应于将数据按位解释为无符号 64 位整数和无符号 32 位整数。 我在运行 Ubuntu 14.04 的 64 位机器上试过这个。它是用股票 gcc 编译器(4.8.4?)编译的。编译器确实会抛出“来自不兼容指针类型的赋值”警告(可以安全地忽略它,因为不兼容的赋值是有意的)。

这是转换和解释“数据”数组中数据的可靠方法,还是建议手动将每个字节一次一个地复制并移动到一个临时变量?

【问题讨论】:

“可以放心忽略”... 不同的字节序会有不同的行为。 【参考方案1】:

您违反了aliasing rules。所以,明确的答案是:

简单地说:你不能有不同类型的指针指向同一个对象。这可能会导致代码损坏,因为编译器实际上确实假设这不会发生并且可能会优化代码。

只是一个非常强烈的提示:不要忽略警告。给出它们是有充分理由的。

最好的方法是将数组中每个元素的数据正确序列化/反序列化为最终类型。这也将避免值的字节顺序(字节顺序)和任何(可能的)填充出现任何问题。

我使用这样的函数:

uint32_t readUInt32(const uint8_t **buffer)

    ... // increment buffer accordingly

这样,我只是沿行传递缓冲区指针,而不必关心调用者的递增。该技术实际上是一个迭代器。

【讨论】:

@hacks:请稍等;-) 哈哈哈哈哈哈。慢慢来。 -1,因为这似乎没有意识到 char* 是一个特殊情况,这可能与这里有关。 (如果它不相关,那值得解释) @Hurkyl:不,我没有监督!您 OTOH 可能没有注意到 OP 将 uint8_t * 分配给不同类型的 两个 指针! 会导致别名失败,而不是uint8_t * 的分配。阅读我提供的链接,你会看到的。【参考方案2】:

编译器确实会抛出“不兼容指针类型的赋值”警告(可以安全地忽略它,因为不兼容的赋值是有意的)。

这个警告不能也不应该被忽略,因为指针确实不兼容。这是有问题的原因是数据的解释取决于使用的硬件 - 特别是机器的字节序。

是否建议手动将每个字节一次一个地复制并移动到一个临时变量中?

这种方法将独立于字节序。或者,您可以使用hton.../ ntoh... 系列函数来强制字节顺序。

【讨论】:

【参考方案3】:

大端机器和小端机器的行为会有所不同,因此最好手动复制和移动每个字节。

【讨论】:

以上是关于指向C中不同数据类型的指针的主要内容,如果未能解决你的问题,请参考以下文章

C 语言指针数据类型 ( 指针步长 | 复杂指针阅读技巧 )

指针浅析

C 语言const 关键字用法 ( 常量指针 - const 在 * 左边 - 修饰数据类型 - 内存不变 | 指针常量 - const 在 * 右边 - 修饰变量 - 指针不变 )

在 C 语言中:我可以让两个不同类型的指针指向同一个地址吗?

C语言的数据类型——指针

C语言的数据类型——指针