由指针调用的结构成员具有指定的不同值

时间:2018-01-12 09:24:34

标签: c struct

我有以下一段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]值而没有指针,我会得到正确的结果。

3 个答案:

答案 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}},则您将从D16D[16]访问内存,该内存部分位于D[19]之外sys_data 1}}超出范围。其他错误值相同。 您可以阅读存储计数器的位置,或者您未向我们展示的其他内容。

答案 2 :(得分:0)

除了其他答案所说的,你正在访问你的数组,好像它们能够包含20个元素,但它们只有19个元素。 D [19]声明了一个由19个元素组成的数组,应该使用D [0]到D [18]来访问,但是你使用&#39; i&#39;进行写作和阅读。它从0到19迭代,这将写入和读取数组的末尾,导致进一步的未定义行为。