我有以下一段C代码,它显示了一个奇怪的结果。 S_data是struct数据类型。有人可以帮助我知道这个的原因
int i;
typedef struct
{
uint8_t D[19];
uint32_t *D_ptr[19];
} sys_data;
代码:
for (i = 0; i < 20; i++) {
S_data.D[i] = 0;
console("%d",S_data.D[i]);
S_data.D_ptr[i] = &S_data.D[i];
}
for ( i = 0; i <20; i++) {
console("Value of var[%d] = %d\n", i, *S_data.D_ptr[i] );
console("Address of var[%d] = %u\n", i, S_data.D_ptr[i] );
}
输出:
Address of var[0] = 536872044
Value of var[1] = 0
Address of var[1] = 536872045
Value of var[2] = 0
Address of var[2] = 536872046
Value of var[3] = 0
Address of var[3] = 536872047
Value of var[4] = 0
Address of var[4] = 536872048
Value of var[5] = 0
Address of var[5] = 536872049
Value of var[6] = 0
Address of var[6] = 536872050
Value of var[7] = 0
Address of var[7] = 536872051
Value of var[8] = 0
Address of var[8] = 536872052
Value of var[9] = 0
Address of var[9] = 536872053
Value of var[10] = 0
Address of var[10] = 536872054
Value of var[11] = 0
Address of var[11] = 536872055
Value of var[12] = 0
Address of var[12] = 536872056
Value of var[13] = 0
Address of var[13] = 536872057
Value of var[14] = 0
Address of var[14] = 536872058
Value of var[15] = 0
Address of var[15] = 536872059
Value of var[16] = 0
Address of var[16] = 536872060
Value of var[17] = 1811939328
Address of var[17] = 536872061
Value of var[18] = 74186752
Address of var[18] = 536872062
Value of var[19] = 289792
Address of var[19] = 536872063
这里var [17]预计为0,但显示不同的值。但如果我直接打印var [17]值而没有指针,我会得到正确的结果。
答案 0 :(得分:2)
您违反了严格的别名规则。(S_data.D_ptr[i] = &S_data.D[i];
)因此它是未定义的行为。你不能像这样将一种类型的指针分配给另一种类型。
typedef struct
{
uint8_t D[19];
uint8_t *D_ptr[19];
} sys_data;
这解决了你的问题。
还使用(如果您将其声明为uint32_t
)打印uint32_t
。
printf("%" PRIu32 "\n", *S_data.D_ptr[i]);
同时打印像这样的指针
printf("%p", (void*)S_data.D_ptr[i]);
答案 1 :(得分:0)
有关 UB 的部分已在coderedoc的答案中解释过。
我想补充一些细节:
在某些计算机上,当您尝试从未正确对齐的地址读取uint32
时,您将收到异常。奇数地址是总线错误,数据提取错误或类似错误的良好候选者。
这是违反严格别名规则的结果。
如果您访问指向D_Ptr[16]
的{{1}},则您将从D16
到D[16]
访问内存,该内存部分位于D[19]
之外sys_data
1}}超出范围。其他错误值相同。
您可以阅读存储计数器的位置,或者您未向我们展示的其他内容。
答案 2 :(得分:0)
除了其他答案所说的,你正在访问你的数组,好像它们能够包含20个元素,但它们只有19个元素。 D [19]声明了一个由19个元素组成的数组,应该使用D [0]到D [18]来访问,但是你使用&#39; i&#39;进行写作和阅读。它从0到19迭代,这将写入和读取数组的末尾,导致进一步的未定义行为。