C中指向不同数据类型的指针
Pointer to different data type in C
我已经在 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 位整数。
我在 64 位机器 运行ning Ubuntu 14.04 上试过这个。它是用标准的 gcc 编译器(4.8.4?)编译的。编译器确实会抛出 "assignment from incompatible pointer type" 警告(可以安全地忽略它,因为不兼容的赋值是有意的)。
这是一种可靠的转换和解释 "data" 数组中数据的方法,还是建议手动将每个字节(一次一个)复制和移动到一个临时变量?
您违反了aliasing rules。所以,明确的答案是:no.
简而言之:你不能让不同类型的指针指向同一个对象。这可能会导致代码损坏,因为编译器实际上会假设这不会发生并且可能会优化代码。
只是一个非常强烈的提示:不要忽略警告。它们是有充分理由的。
最好的方法是将数组中每个元素的数据正确地 serialize/deserialize 为最终类型。这也将避免值的字节顺序(字节顺序)和任何(可能的)填充的任何问题。
我使用这样的函数:
uint32_t readUInt32(const uint8_t **buffer)
{
... // increment buffer accordingly
}
这样一来,我只需沿行传递缓冲区指针,而不必关心调用者的递增。该技术实际上是一个迭代器。
The compiler does throw the "assignment from incompatible pointer type" warning (which can be safely ignored because the incompatible assignment is intended).
这个警告不能也不应该被忽略,因为指针确实不兼容。这是有问题的原因是数据的解释取决于所使用的硬件——具体来说,取决于机器的字节顺序。
would it be better recommended to manually copy and shift each byte, one at a time, to a temporary variable?
这种方法与字节序无关。或者,您可以使用 hton{...}
/ ntoh{...}
系列函数来强制字节顺序。
big-endian 机器和 little-endian 机器之间的行为会有所不同,因此您最好手动复制和移动每个字节。
我已经在 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 位整数。 我在 64 位机器 运行ning Ubuntu 14.04 上试过这个。它是用标准的 gcc 编译器(4.8.4?)编译的。编译器确实会抛出 "assignment from incompatible pointer type" 警告(可以安全地忽略它,因为不兼容的赋值是有意的)。
这是一种可靠的转换和解释 "data" 数组中数据的方法,还是建议手动将每个字节(一次一个)复制和移动到一个临时变量?
您违反了aliasing rules。所以,明确的答案是:no.
简而言之:你不能让不同类型的指针指向同一个对象。这可能会导致代码损坏,因为编译器实际上会假设这不会发生并且可能会优化代码。
只是一个非常强烈的提示:不要忽略警告。它们是有充分理由的。
最好的方法是将数组中每个元素的数据正确地 serialize/deserialize 为最终类型。这也将避免值的字节顺序(字节顺序)和任何(可能的)填充的任何问题。
我使用这样的函数:
uint32_t readUInt32(const uint8_t **buffer)
{
... // increment buffer accordingly
}
这样一来,我只需沿行传递缓冲区指针,而不必关心调用者的递增。该技术实际上是一个迭代器。
The compiler does throw the "assignment from incompatible pointer type" warning (which can be safely ignored because the incompatible assignment is intended).
这个警告不能也不应该被忽略,因为指针确实不兼容。这是有问题的原因是数据的解释取决于所使用的硬件——具体来说,取决于机器的字节顺序。
would it be better recommended to manually copy and shift each byte, one at a time, to a temporary variable?
这种方法与字节序无关。或者,您可以使用 hton{...}
/ ntoh{...}
系列函数来强制字节顺序。
big-endian 机器和 little-endian 机器之间的行为会有所不同,因此您最好手动复制和移动每个字节。