这是我的功能:
void abc(char *def, unsigned int w, unsigned int x, unsigned int y, unsigned int z)
{
printf("val 1 : %d\n", w);
printf("val 2 : %d\n", x);
printf("val 3 : %d\n", y);
printf("val 4 : %d\n", z);
}
这里是我调用此函数的地方:
unsigned int exp[4] = { 1, 2, 3, 4 };
unsigned short count = 0;
abc(anyarray, exp[count++], exp[count++], exp[count++], exp[count++]);
这是我期望的输出:
val1 : 1
val2 : 2
val3 : 3
val4 : 4
但我得到的完全相反:
val1 : 4
val2 : 3
val3 : 2
val4 : 1
我不知道为什么?任何帮助将不胜感激。
答案 0 :(得分:8)
从标准文档 5.4
除非另有说明,否则单个运算符的操作数和单个表达式的子表达式的评估顺序, 并且副作用发生的顺序是未指定的58)在前一个和下一个序列点之间a 通过表达式的计算,标量对象的存储值最多只能修改一次。此外,先前 只能访问值以确定要存储的值。应满足本款的要求 每个允许的完整表达子表达式的排序;否则行为未定义。
标准文档本身的一个例子,
i = v[i ++]; / / the behavior is undefined
出于同样的原因
abc(anyarray, exp[count++], exp[count++], exp[count++], exp[count++]);
未定义..
答案 1 :(得分:4)
您不应该在同一语句中多次使用同一变量操作的++运算符。未定义执行操作的顺序。
尝试:
abc(anyarray, exp[count], exp[count+1], exp[count+2], exp[count+3]);
count += 4;
答案 2 :(得分:2)
您已经调用了未定义的行为,通过多次修改count
而没有干预sequence point。
答案 3 :(得分:1)
您指望从左到右评估的参数。您不能对它们被评估的顺序做出任何假设。在这种情况下,看起来编译器从右到左评估它们。
此外,您可能希望查找序列点,因为您可能不应该以这种方式使用++运算符。
答案 4 :(得分:1)
abc(anyarray, exp[count++], exp[count++], exp[count++], exp[count++]);
abc
参数的评估顺序是未指定,但表达式调用未定义行为,因为您正在尝试修改变量count
两个序列点之间不止一次。
此外,在printf()
中使用不正确的格式说明符也会调用UB。请确保您在%u
中使用了正确的格式说明符(即unsigned int
printf()
)。
答案 5 :(得分:0)
你得到这个是因为你根据你的问题调用了adb(exp,a,b,c,d)
,但是在调用函数d
时,首先在堆栈上推送然后c ,b
相对。当您在最后一个参数处通过exp[count++]
时,它将首先处理以推送堆栈意味着首先按下2然后按3然后按4.然后在调用函数pop中执行,以便得到w=4 x=3 y=2 z=1
就是它。
答案 6 :(得分:-4)
这是因为调用约定。在_cdecl中,c / c ++程序的默认调用约定(根据microsoft),参数以相反的顺序在堆栈上传递给函数。因此,参数也以相反的顺序进行评估。