C语言函数内形式参数的入栈顺序是UB行为

最近在学校论坛看到一个关于C语言的问题,如下文这段代码,期待中的输出应该是5,5,但是在gcc中的结果实际是7,3,而在clang中的结果则是期望中的5,5。为什么会产生这种区别呢?其原因就在于printf("%d,%d\n", (++p)->a, (p++)->a);这句,因为在形参传参过程中,左参数(++p)->a和右参数(p++)->a不是彼此独立的,而是会相互影响,因此编译器在解释函数传参过程中,从左到右入栈还是从右到左入栈的顺序就至为关键,不凑巧的时,这个顺序在C语言标准中是没有定义的,也就是所谓的未定义行为Undefined Behavior(UB)。这个就是导致以下代码段在clang和gcc中的结果不同的原因。

这个例子告诉我们,我们在实际的编程过程中,不要使用太多“骚操作”,这样很容易造成意外的bug。我们的编码原则应该是高内聚低耦合, 一段函数应该尽可能减少其意外的影响面,比如printf函数就应该只考虑打印信息,不应该把自加的操作引入其中。另外,C/C++语言中还有其他UB行为,比如不同文件中定义的全局变量的定义顺序是未定义的,这样很容易导致一些意外之外的bug。

#include <stdio.h>
int main(void)
{
    struct ks {
        int a;
        int* b;
    }s[4], * p;
    int n = 1, i;
    for (i = 0; i < 4; i++) {
        s[i].a = n;
        s[i].b = &s[i].a;
        n = n + 2;
    }
    p = &s[0];
    p++;
    printf("%d,%d\n", (++p)->a, (p++)->a);
    return 0;
}

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 1
收藏 2
关注 50
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧