我一直在查看一些代码,我看到了一个有趣的事情:在某些时候有一条线
pTable[i] = ((int *)val)[i]; // case 1
pTable
是uint16_t
指针,val是void
指针;所以我想把它改成
pTable[i] = ((uint16_t *)val)[i]; // case 2
并发现输出中的一些差异。所以我开始首次亮相并看到内存的排列方式不同。假设void指针中的数据类似于val[0] = 0x1234
和val[1] = 0x5678
addr 56781234
addr 00001234 00005678
代码是一个巨大的,而不是我的,我不能放在这里,但它是一个解析器(它从文件中读取值)。到达该无效指针的内容可能是int
或float
值(在我的情况下,它们是int
)。
我想这是解释指针数据的问题,但我自己无法解释,有人能解释一下吗?感谢
答案 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
的指针读取此类值将具有未定义的行为,因为这违反了指针别名规则。