使用指定的初始化程序初始化数组时出现奇怪的值 [英] Strange values while initializing array using designated initializers

查看:261
本文介绍了使用指定的初始化程序初始化数组时出现奇怪的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我初始化下面的数组时,除values[3]以外的所有输出都可以.由于某些原因,初始化为values[0]+values[5]values[3]输出很大的数字.我的猜测是,我试图在values[0]+values[5]正确分配之前将它们分配给内存,但是如果有人可以解释的话,那会很好.

When I initialize the array below all the output looks ok except for values[3]. For some reason values[3] initialized as values[0]+values[5] is outputting a very large number. My guess is that I am trying to assign values[0]+values[5] before they are properly stored in memory but if someone could explain that would be great.

int main (void)
{

    int values[10] = { 
        [0]=197,[2]=-100,[5]=350,
        [3]=values[0] + values[5],
        [9]= values[5]/10
    };

    int index;

    for (index=0; index<10; index++)
        printf("values[%i] = %i\n", index, values[index]);


    return 0;
}

输出如下:

values[0] = 197
values[1] = 0
values[2] = -100
values[3] = -1217411959
values[4] = 0
values[5] = 350
values[6] = 0
values[7] = 0
values[8] = 0
values[9] = 35

推荐答案

由于C99标准草案6.7.8中未指定初始化列表表达式的计算顺序,因此您似乎在此处受到未指定的行为的约束. :

It looks like you are subject to unspecified behavior here, since the order of evaluation of the initialization list expressions is unspecified, from the draft C99 standard section 6.7.8:

初始化期间发生任何副作用的顺序 列表表达式未指定. 133)

The order in which any side effects occur among the initialization list expressions is unspecified.133)

注释133说:

尤其是,评估顺序不必与顺序相同 子对象初始化.

In particular, the evaluation order need not be the same as the order of subobject initialization.

据我所知,备份笔记133的规范性文本将来自6.5部分:

As far as I can tell, the normative text that backs up note 133 would be from section 6.5:

除非后面有指定,否则...的评估顺序 子表达式以及发生副作用的顺序都 未指定.

Except as specified later [...] the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.

,我们可以看到 inializer 6.8的完整表达式(强调我的):

and we can see that an intializer is a full-expression from 6.8 (emphasis mine):

完整表达式是不属于另一个表达式的表达式 表达式或声明符. 以下每个都是完整的表达式:初始化程序; [...]

A full expression is an expression that is not part of another expression or of a declarator. Each of the following is a full expression: an initializer; [...]

回头看一看我的旧的C ++答案,其中涵盖了初始化程序中的序列点,并将完全表达在另一个地方,我最初得出的结论是,我意识到6.7.8中包含 initializer 两次的语法:

After looking back at one of my old C++ answers that covered sequence points within an initializer and which places the full-expression in a different place then I originally concluded, I realized the grammar in 6.7.8 contained initializer twice:

initializer:
    assignment-expression
    { initializer-list }
    { initializer-list , }
initializer-list:
    designationopt initializer
    initializer-list , designationopt initializer

我最初没有注意到这一点,并认为关于 full-expressions 的陈述适用于上述语法的顶部元素.

I originally did not notice this and thought the statement on full-expressions applied to the top element in the above grammar.

我现在认为,像C ++一样,完整表达适用于 initializer-list 中的每个 initializer ,这使我以前的分析不正确.

I now believe like C++ the full-expression applies to each initializer within the initializer-list which make my previous analysis incorrect.

缺陷报告439 确认了我的怀疑确实如此,它包含以下示例:

Defect report 439 confirmed my suspicion that this was indeed the case, it contains the following example:

#include <stdio.h>

#define ONE_INIT      '0' + i++ % 3
#define INITIALIZERS      [2] = ONE_INIT, [1] = ONE_INIT, [0] = ONE_INIT

int main()
{
    int i = 0;
    char x[4] = { INITIALIZERS }; // case 1
    puts(x);
    puts((char [4]){ INITIALIZERS }); // case 2
    puts((char [4]){ INITIALIZERS } + i % 2); // case 3
}

它说:

在每次使用INITIALIZERS宏时,变量i都会递增 三次.在情况1和2中,没有未定义的行为,因为 增量在不确定地排序的表达式中 彼此之间,而不是无序的.

In every use of the INITIALIZERS macro, the variable i is incremented three times. In cases 1 and 2, there is no undefined behavior, because the increments are in expressions that are indeterminately sequenced with respect to one another, not unsequenced.

所以INITIALIZERS中的每个初始化符都是完整表达式.

由于此缺陷报告是针对C11的,因此值得注意的是,在此问题的规范性文本中,C11比C99更冗长,并且说:

Since this defect report is against C11 it is worth noting that C11 is more verbose then C99 in the normative text on this issue and it says:

对初始化列表表达式的求值为 相对于彼此不确定地排序,因此 未指定发生副作用的顺序. 152)

The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified.152)

在将values中的各个元素分配给以下表达式之前求出以下表达式的情况下,存在不确定的行为:

There is undefined behavior in the case where the following expressions are evaluated before the respective elements in values are assigned to:

 values[0] + values[5]

或:

 values[5]/10

这是未定义的行为,因为使用不确定的值会引发未定义的行为.

This is undefined behavior since using an indeterminate value invokes undefined behavior.

在这种情况下,最简单的解决方法是手动执行计算:

In this specific case the simplest work-around would be to perform the calculations by hand:

int values[10] = { 
    [0]=197,[2]=-100,[5]=350,
    [3]= 197 + 350,
    [9]= 350/10
};

还有其他选择,例如在初始化后对元素39进行赋值.

There are other alternatives such as doing the assignments to element 3 and 9 after the initialization.

这篇关于使用指定的初始化程序初始化数组时出现奇怪的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆