我正在用C编写非破坏性转换例程,我刚刚意识到(至少在Visual C ++中)函数是以相反的顺序解析的。
所以:
main()
{
char* psString[] = { "Hello", "World", "World2", "World3" };
printf("%s - %s - %s - %s\n",
H2A_N(psString[0]),
H2A_N(psString[1]),
H2A_N(psString[2]),
H2A_0(psString[3]));
return 1;
};
我的代码不是可重入的,只能在一个线程中运行,因此我将使用静态字符数组来存储结果。
我的计划是有一个函数H2A_0,它将输出写入缓冲区的开头,并留下下一个地址,以便后续调用H2A_N。
我确实意识到这种方法存在一些缺点但是我必须将这个转换例程应用到很多现有代码中,所以越简单越好(我不想乱用释放内存)。
我的问题是:
答案 0 :(得分:7)
没有明确的参数评估顺序。编译器可以随意决定评估它们的顺序。
该标准的最新版本C11如下所述,§6.5.2.2/ 10:
在评估函数指示符和实际值之后有一个序列点 参数但在实际调用之前。调用函数中的每个评估(包括 其他函数调用)在其之前或之后没有特别顺序排序 被调用函数体的执行是相对于不确定地排序的 执行被调用的函数。
如果您希望强制执行特定的评估顺序,则需要将表达式从函数调用中拉出,并将它们保存到局部变量中。
int param1 = foo(...);
int param2 = bar(...);
DoSomething(param1, param2);
有更好的方法吗?
很可能。具有函数返回值并且还将副作用应用于固定长度静态分配的缓冲区通常不被认为是最佳实践。但是,我不想告诉你如何解决你的问题,因为我对这个问题知之甚少。
答案 1 :(得分:1)
它是C标准的一部分来解决功能(当它们是 以相反的顺序作为参数传递给其他函数。
函数参数被计算为表达式;因此,它是实现定义的,就像在x = f() + g()
中一样。如果在f()
之前调用g()
依赖于编译器到编译器,请查看sequence point。
有些编译器(例如icc
)会对此发出警告:
备注#981:操作数以未指定的顺序进行评估
答案 2 :(得分:-2)
应该先检查一下。没有明确的解决顺序。大多数编译器似乎从右到左解析。