8
回答
请教一个C语言顺序点的问题。。。。
百度AI开发者大赛带你边学边开发,赢100万奖金,加群:418589053   

各位大神,小生才疏学浅请教一个c语言顺序点问题,代码如下:

#include “stdio.h”

void f(int i,int j)
{
    printf("%d ,%d  \n",i,j);
}

int main()
{
    int k=1;
    f(k,k++);
    return 0;
}

根据顺序点的知识,为什么k传入的值是2,而k++传入的值是1?小生编译器是gcc,是因为编译器不同,顺序就运算顺序就不同吗?



举报
mcu小生
发帖于4年前 8回/2K+阅
共有8个答案 最后回答: 4年前

参数入栈顺序是和具体编译器实现相关的。

C方式参数入栈顺序(从右至左)的好处就是可以动态变化参数个数。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反。

因此,C语言函数参数采用自右向左的入栈顺序,主要原因是为了支持可变长参数形式。

--- 共有 1 条评论 ---
wangxigui可以在深入解释下:动态变化参数个数 的意思吗? 4年前 回复

k++是指先运行表达式,再加1;
k先赋值给方法,然后加1,然后k值变成了2,然后k再赋值给函数,最后调用函数,所以有先2后1的输出。
核心细节 可能 是表达式计算用的先进后出

从右向左,解析并编译。哈。理解这个就ok了。另外给楼主个提示,我学习和开发c语言的程序,也快20年了。类似你这样的问题,从来不纠结。。对于++i,i++,我一向保持,仅发生在通用实现方式,或独立一条语句中。哈,所谓通用实现方式,例如:

for(i = 0; i < 10 ;i++)

*p1++= *p2++;

其他情况几乎都是独立一个语句折腾,省得自己或别人对代码还要反复核对。。。累不累?反正我是累了。

根据你的描述是,函数f()的解析是从右到左的,而i++的i是用了再加,所以i++传入的值是1,自加后i的值就是2了。

引用来自“中山野鬼”的评论

从右向左,解析并编译。哈。理解这个就ok了。另外给楼主个提示,我学习和开发c语言的程序,也快20年了。类似你这样的问题,从来不纠结。。对于++i,i++,我一向保持,仅发生在通用实现方式,或独立一条语句中。哈,所谓通用实现方式,例如:

for(i = 0; i < 10 ;i++)

*p1++= *p2++;

其他情况几乎都是独立一个语句折腾,省得自己或别人对代码还要反复核对。。。累不累?反正我是累了。

我也不是纠结这个问题,我就想搞明白这是为什么,至于代码我也不会写成那样,于人于己都不好。。。。

这个就是sequence point和side effect问题.
func(f1(),g1()); 

上面的表达式到底先执行那个函数 顺序是不确定的. 是Unspecified.  
函数调用会产生一个side effect, 而调用函数之前是一个Sequence Point. 所以可以确定func()将会在f1(), g1()之后执行. 同时两个Sequence Point之间的side effect执行顺序是unspecified的. 所以先执行f1()还是先执行g1() 是不确定的. 


这个用clang去编译得到的编译器警告就说的很清楚了, 

int func(int a,int b)
{
    return 0;
}
int main(void)
{
    int i =0;
    i = ++i + 1;
    func(i,i++);
    return 0;
}
>>> clang t.c
t.c:8:9: warning: multiple unsequenced modifications to 'i' [-Wunsequenced]
    i = ++i + 1;
      ~ ^
t.c:9:13: warning: unsequenced modification and access to 'i' [-Wunsequenced]
    func(i,i++);
         ~  ^
2 warnings generated.



--- 共有 1 条评论 ---
PYPlus关于顺序点, side effect的定义和说明在ISO/IEC 9899:1990的5.1.2.3节和Annex C 4年前 回复

引用来自“中山野鬼”的评论

从右向左,解析并编译。哈。理解这个就ok了。另外给楼主个提示,我学习和开发c语言的程序,也快20年了。类似你这样的问题,从来不纠结。。对于++i,i++,我一向保持,仅发生在通用实现方式,或独立一条语句中。哈,所谓通用实现方式,例如:

for(i = 0; i < 10 ;i++)

*p1++= *p2++;

其他情况几乎都是独立一个语句折腾,省得自己或别人对代码还要反复核对。。。累不累?反正我是累了。

引用来自“mcu小生”的评论

我也不是纠结这个问题,我就想搞明白这是为什么,至于代码我也不会写成那样,于人于己都不好。。。。
有些事情,只有你真的做更深层的东西时,才能真正理解。否则就是今天会了。明年也忘了。对自己工作也没有帮助。哈。
顶部