【发布时间】:2016-11-11 22:06:36
【问题描述】:
问题
以下是将指向 16 位值的指针转换为指向 32 位值的指针的代码:
int low_level_read(uint32_t * read_data)
{
// some low level access to get 32-bit read here
}
int i2c_read(uint16_t * data)
{
low_level_read((uint32_t *) data);
printf("data=0x%X\n", *data);
}
预期:
- low_level_read 获取:0x0000C101
- i2c_read 获得:0xC101
观察到:
- low_level_read 获取:0x0000C101
- i2c_read 获得:0x0000
为什么它看起来像是在截断/切断 最不重要的 16 位?
我对这个问题的解决方案
如果 i2c_read() 被修改为如下所示,那么这将按预期工作:
int i2c_read(uint16_t * data)
{
uint32_t raw_data;
low_level_read(raw_data);
*data = (uint16_t) raw_data;
}
没关系,但我仍然想了解为什么第一段代码会这样。
我对原因的有根据的猜测
当我们传入指向 i2c_read() 的指针时,它是 8 位的:
pointer address 0x100 ->
+--+--+--+--+--+--+--+--+
7 6 5 4 3 2 1 0
+--+--+--+--+--+--+--+--+
但是,当转换为 (uint32_t *) 时,它会将内存位置的大小“增长”为 32 位:
pointer address 0x100 ->
+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
31 30 29 28 27 26 25 24 .... 7 6 5 4 3 2 1 0
+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
32 位值被放入该位置。 但是当它截断它时,它实际上会截断位 [15:0] 并将指针地址保留为 0x100。这意味着当它返回时,我最终会看到位 [31:16] 因此全为零。
这是我最好的猜测。
有人能解释一下吗?谢谢:)。
【问题讨论】:
-
违反有效类型规则 -> 未定义行为。
-
当你调用
printf()时,*data是一个16位的量;这就是传递给printf()的内容。如果要传递 32 位数量,则需要一个指向 32 位数量的指针,但*data是,并且永远是 16 位数量。 -
查找“字节序”。
-
将打印更改为
printf("data=0x%X\n", (unsigned int)*data);,如果这会更改输出,请告诉我们 -
对齐冲突是第三个可能的问题。它会改善显示调用代码的问题(特别是如何获取参数)