【问题标题】:C pointer cast - value truncationC 指针强制转换 - 值截断
【发布时间】: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);,如果这会更改输出,请告诉我们
  • 对齐冲突是第三个可能的问题。它会改善显示调用代码的问题(特别是如何获取参数)

标签: c pointers


【解决方案1】:

i2c_read() 正在接收参数 uint16_t *data,它说“这里是 2 字节内存的地址”:

data --> [ByteA][ByteB]

当您执行转换 (uint32_t*)data 时,您现在声称 data 是 4 字节内存的地址:

data --> [ByteA][ByteB][ByteC][ByteD]

真诚地,low_level_read() 使用您作为uint32_t* 传递的地址,并将所有4 个字节的内存填充为[00][00][C1][01]这很糟糕。 指针 data[ByteC][ByteD] 没有任何权限,现在您已经覆盖了可能为程序的其他部分保存一些重要数据的内存。

回到printf() 处的i2c_read(),变量data 变回只是一个uint16_t*,而*data 仅读取[ByteA][ByteB] 作为要打印的值([00][00])。
如果您改为调用 printf("℅08X", *(uint32_t*)data),则会读取 4 个字节并打印 0x00000C01

要修复您的代码,请确保 i2c_read()low_level_read() 的参数类型相同。

【讨论】:

  • 是的,这正是我认为的原因。你有这方面的参考吗?
  • uhh...此链接的“类型的东西”部分似乎解决了这个主题 - (cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/…。请注意,它有一个错字 - sizeof(short) --> 2跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 2013-09-13
相关资源
最近更新 更多