C 指针调用的结构成员指定了不同的值

C 指针调用的结构成员指定了不同的值,c,struct,C,Struct,我有下面一段C代码,它显示了一个奇怪的结果。 S_数据是一种结构数据类型。有人能帮我知道原因吗 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]);

我有下面一段C代码,它显示了一个奇怪的结果。 S_数据是一种结构数据类型。有人能帮我知道原因吗

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] );
       }

此处var[17]预计为0,但显示了不同的值。但是如果我不使用指针直接打印var[17]值,我会得到正确的结果。

您违反了严格的别名规则。(
S_data.D_ptr[i]=&S_data.D[i];
)因此这是未定义的行为。不能像这样将一种类型的指针分配给另一种类型的指针

typedef struct
{
  uint8_t D[19];
  uint8_t *D_ptr[19];

} sys_data;
这为您解决了问题

还可以使用打印
uint32\u t
(如果您将其声明为
uint32\u t

也可以这样打印指针

printf("%p", (void*)S_data.D_ptr[i]);
关于UB的部分已在coderedoc的回答中解释

我想再补充一些细节:

在某些机器上,当您试图从未正确对齐的地址读取
uint32
时,会出现异常。奇数地址是总线错误、数据提取错误或类似错误的最佳候选地址。 这是违反严格的别名规则的结果

如果您访问指向
D16
D\u Ptr[16]
,您将访问
D[16]
D[19]
的内存,该内存部分位于
sys\u数据
之外,因为
var[19]
超出范围。其他不正确的值也是如此。
您可以读取计数器的存储位置,或者其他您没有显示给我们的内容。

除了其他答案所说的内容之外,您正在访问数组,就好像它们能够包含20个元素,但它们的长度只有19个元素一样。D[19]声明了一个由19个元素组成的数组,应该使用D[0]到D[18]访问该数组,但是您都在使用从0到19的“i”进行写入和读取,这将在数组末尾写入和读取,从而导致进一步的未定义行为。

谢谢,解决了问题。但如果我将两者都初始化为32位int,我仍然会遇到问题。uint32_t D[19];uint32_t*D_ptr[19];结果:var[0]的值=536872044 var[0]的地址=0@AkhilJoy看起来好像您在打印中切换了指针和内容。这是printf代码控制台(“var[%d]的值=%u\n”,i,*S_data.d_ptr[i]);控制台(“变量[%d]的地址=%u\n”,i,S_data.d_ptr[i]);但只有var[0]为无符号32位获取不同的值。风险值[0]=536872044风险值地址[0]=0风险值[1]=0风险值地址[1]=536872048风险值地址[2]=0风险值地址[3]=0风险值地址[3]=536872056风险值地址[4]=0风险值地址[4]=536872060风险值地址[5]=0风险值地址[5]=536872064等等我哪里出了问题?@Gerhardh不,我没有。。除var[0]外,其余值的&address都是正确的。@AkhilJoy可能您对位于该结构之前的其他变量的越界元素有一些更非法的访问。对于任何结论,你都显示了太少的代码。C还是C++?选择一个。请将更新的代码和结果添加到问题中。(不要删除原始问题)请同时显示使用该结构的整个函数。
printf("%" PRIu32 "\n", *S_data.D_ptr[i]);
printf("%p", (void*)S_data.D_ptr[i]);