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

Ale*_*eal 2 c pointers unsigned-char unsigned-integer

我已经在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;
}
Run Code Online (Sandbox Code Playgroud)

并收到以下预期输出:

506097522914230528
50462976
117835012
Run Code Online (Sandbox Code Playgroud)

输出是正确的,并且对应于数据的按位解释为无符号的64位整数和无符号的32位整数。我在运行Ubuntu 14.04的64位计算机上尝试了此操作。它是用普通的gcc编译器(4.8.4?)编译的。编译器的确发出“来自不兼容指针类型的赋值”警告(可以放心地忽略它,因为有意使用不兼容的赋值)。

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

too*_*ite 5

您违反了别名规则。因此,明确的答案是:

简要地说:您不能让不同类型的指针指向同一对象。这可能会导致代码损坏,因为编译器实际上确实认为不会发生这种情况,并且可能会优化代码。

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

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

我使用这样的函数:

uint32_t readUInt32(const uint8_t **buffer)
{
    ... // increment buffer accordingly
}
Run Code Online (Sandbox Code Playgroud)

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