写入int与uint16_t时的内存填充

时间:2018-01-25 12:47:11

标签: c++ c pointers

我一直在查看一些代码,我看到了一个有趣的事情:在某些时候有一条线

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

pTableuint16_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)。

我想这是解释指针数据的问题,但我自己无法解释,有人能解释一下吗?感谢

2 个答案:

答案 0 :(得分:4)

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

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

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

'i'次sizeof(val[0])将确定val地址的偏移量。

答案 1 :(得分:2)

让我们将行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的指针读取此类值将具有未定义的行为,因为这违反了指针别名规则。