在强制转换为字节数组后打印值

时间:2017-07-06 11:21:02

标签: c arrays casting

我正在尝试了解如何调试已序列化为字节数组的数据。该代码显示了解决方案试验失败的问题。

我想要实现的是获得仅12345678的整个数组成员78的打印。

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

int main()
{
    uint32_t words[2] = {0x12345678, 0x87654321};
    char * struct_array = &words;

    printf("%x \n", *struct_array);   //  78   prints a lsb byte from the first array member
    printf("%lx \n", *struct_array);   // 78   assuming it would print more than a single byte

    //Perhaps it's printing a single byte because of the char pointer.
    printf("%x \n", (uint32_t) *struct_array);   // 78
    printf("%lx \n", (uint32_t) *struct_array);  // 78
    // Nope
}

3 个答案:

答案 0 :(得分:2)

struct_array的类型为char*,i。即指向char的指针。 *struct_array然后解引用单个char(单个字节),因此只查看words占用的内存中的第一个字节。你得到0x78,因为显然你的机器是一个小端,所以数据以逆字节顺序存储。将char转换回uint32_t不会改变任何内容 - 值为0x78,它适合32位整数,因此它保持为0x78。

如果你想获得整个价值,你需要阅读整个价值,i。即取消引用指向uint32_t的指针,这意味着您需要在解除引用之前转换指针:

*(uint32_t*)struct_array

答案 1 :(得分:2)

此:

char * struct_array = &words;

struct_array变为指向char的指针。取消引用会为您提供char,您无法通过投射来改变之后的

您当然可以在解除引用之前强制转换指针(但风险未定义的行为):

printf("%x\n", *(uint32_t *) struct_array);

当然,最好使用正确的反序列化代码,而不是试图通过指针解除引用欺骗来强制它。如果你有一堆你知道的字节代表一个更大的数字,那就把它放在一起吧。

要扩展最后一点,如果这是一个实际的字节数组:

const uint8_t data[] = { 0x78, 0x56, 0x34, 0x12 };

并且您希望将它们重新组合成一个32位无符号整数,假设您执行的是小端存储:

const uint32_t x = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
printf("x de-serialized into 0x%08x\n", x);

这会打印x de-serialized into 0x12345678,所有这些都不会违反任何内容。 :)

答案 2 :(得分:1)

//expected it would print more than a single byte

这种期望是错误的。取消引用已经完成,当时struct_array的类型为char *。然后(提升)的值用作转换说明符的参数。

要强调的是,所提供的参数类型和转换说明符并不像您预期​​的那样内部相关,程序员的工作就是让两者保持一致。

如果希望缓冲区生成源类型的原始值,则需要使用强制转换将指针变为实际类型,然后取消引用以获取该值。在取消引用之后,演员在这里毫无意义。

注意事项:您只能将指针强制转换回原始类型或兼容类型,而不仅仅是“任何”其他类型,这会破坏严格的别名