写入 int 与 uint16_t 时的内存填充

Memory filling when writing int vs uint16_t

本文关键字:内存 填充 int uint16 写入      更新时间:2023-10-16

我一直在浏览一些代码,我看到了一件有趣的事情:在某些时候有一行

pTable[i] = ((int *)val)[i]; // case 1

pTable 是一个uint16_t指针,val 是一个void指针;所以我想把它改成

pTable[i] = ((uint16_t *)val)[i]; // case 2

并发现了输出中的一些差异。所以我开始首次亮相,看到记忆的排列方式不同。假设 void 指针中的数据类似于 val[0] = 0x1234val[1] = 0x5678

  • 在第一种情况(案例 1(中,内存转储显示addr 56781234
  • 而在第二个(案例 2(中,内存转储显示addr 00001234 00005678

代码是一个巨大的,不是我的,我不能放在这里,但它是一个解析器(它从文件中读取值(。到达该空指针的内容可能是intfloat值(在我的情况下,它们是int(。

我想这是关于解释指针数据的事情,但我自己无法解释,有人可以向我解释吗?谢谢

int在您的

系统上可能是 32 位的,而uint16_t是 16 位的。

这意味着在第一种情况下,您将在val[i]地址访问 32 位信息,在第二种情况下只需访问 16 位信息。

内存中的位置也会发生变化,因为[]运算符会根据val的类型转换为此*(val + i)。换句话说,除非i为 0,否则((int *)val)[i];((uint16_t *)val)[i]; 不在同一地址;

"i"乘以sizeof(val[0])将确定val地址的偏移量。

让我们将行pTable[i] = ((int *)val)[i];分成几部分,以便更容易理解:

void* val = something;             // val points to an object of some type.
uint16_t* pTable = something_else; // ptable points to a uint16_t object
int* intPtr = (int *)val; // We assume that val points to an int object.
int value = intPtr[i];    // Furthermore, we assume that the pointed int
                          // object is within an array of int objects.
                          // This expression gets the value of an int
                          // object that is i'th sibling element after
                          // the one pointed by val.
uint16_t converted = value; // This step is an implicit conversion
                            // in the original line.
pTable[i] = converted; // we assume that pTable also points to an
                       // element of an array and assign the i'th 
                       // successor of element pointed by pTable

因此,如果将强制转换从 (int*) 更改为 (uint16_t*) ,那么您将假设val指向一个uint16_t数组。显然,这与val指向一系列int的假设相矛盾。

因此,如果我们假设原始程序是正确的,那么val确实指向一个 int数组 .因此,使用指向uint16_t的指针读取此类值将具有未定义的行为,因为这违反了指针别名规则。