xjr1022
V2EX  ›  C

C 语言,碰到个很让人疑惑的问题

  •  
  •   xjr1022 · Dec 4, 2018 · 4656 views
    This topic created in 2897 days ago, the information mentioned may be changed or developed.
    
    //声明函数
    void test(int a, int b);
    
    int main() {
    	int a = 2;
    	test(a, a++);
    	return 0;
    }
    
    void test(int x, int y) {
    
    	printf("x=%d,y=%d", x, y);
    
    }
    
    //运行结果 
    x=3,y=2
    

    想请教一下这个是为什么呢,明明给形参 y 传递的是自增的量,怎么就 x 变成 3,而 y 还是 2,

    Supplement 1  ·  Dec 4, 2018
    ![][https://i.loli.net/2018/12/04/5c065015bdaba.png]
    刚得到的答案,大家看看对吗
    45 replies  •  2018-12-14 10:27:06 +08:00
    shylockhg
    shylockhg
    Dec 4, 2018
    1
    从右边传参数
    xjr1022
    xjr1022
    OP
    Dec 4, 2018
    2
    @shylockhg 麻烦您能说的详细点吗,谢谢了
    misaka19000
    misaka19000
    Dec 4, 2018
    3
    在我电脑上面的运行结果
    x=2,y=2
    make
    make
    Dec 4, 2018❤️1
    4
    a++的返回值是自增之前的值,++a 的返回值才是自增之后的值
    函数调用最后的参数先压栈
    wutiantong
    wutiantong
    Dec 4, 2018❤️2
    5
    在 C++里这属于典型的 ub 了,因为函数传参时 eval 顺序是未定义的。
    单就这个例子来说,先算了(a++) 后算了(a),结果没毛病。
    shylockhg
    shylockhg
    Dec 4, 2018
    6
    这个很尴尬。。。
    clang 3,2
    gcc 2,2
    shylockhg
    shylockhg
    Dec 4, 2018
    7
    @shylockhg 不过 clang 报了警告,估计对这个做了 trick 处理
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone❤️1
    8
    视 calling convention 而定吧
    shylockhg
    shylockhg
    Dec 4, 2018❤️1
    9
    @shylockhg 反了
    clang 2,2
    gcc 3,2
    lovefantasy
    lovefantasy
    Dec 4, 2018 via Android
    10
    等一个解释
    KingHL
    KingHL
    Dec 4, 2018❤️4
    11
    谁这么写代码,直接打死
    xjr1022
    xjr1022
    OP
    Dec 4, 2018
    12
    @KingHL 是一道蛋疼的试题
    WuwuGin
    WuwuGin
    Dec 4, 2018❤️1
    13
    The language clearly says that certain things lead to undefined behavior. There is no problem, there is no "should" involved. If the undefined behavior changes when one of the involved variables is declared volatile, that doesn't prove or change anything. It is undefined; you cannot reason about the behavior.

    https://stackoverflow.com/a/949443

    https://en.wikipedia.org/wiki/Sequence_point

    总结:在实际编程中,不应该出现这种二义性的行为。探讨此类问题没有实际意义。
    des
    des
    Dec 4, 2018 via Android
    14
    不要这么写,这都什么鬼。顺手给你加一点好了
    test(++a, a++)
    KingHL
    KingHL
    Dec 4, 2018❤️2
    15
    参数入栈顺序从右向左,具体实现还要看不同的编译器行为,实际工程应用中,应该禁止这种不确定性的代码。如果是试题的话,估计是在考察你参数入栈顺序这个知识点。
    xjr1022
    xjr1022
    OP
    Dec 4, 2018
    17
    @WuwuGin 是的,真实开发相信没人这么写,这是一道考研真题。。。。
    xjr1022
    xjr1022
    OP
    Dec 4, 2018
    18
    @des 这就要问出题老师怎么想的了,哈哈
    xjr1022
    xjr1022
    OP
    Dec 4, 2018
    19
    @misaka19000 试试 gcc 下编译,有惊喜
    WordTian
    WordTian
    Dec 4, 2018 via Android
    20
    看编译器用的什么调用约定。。。
    就是参数是从左往右还是从右往左
    kokutou
    kokutou
    Dec 4, 2018 via Android
    21
    @xjr1022
    那就只能看卷子上或考试说明上说的用啥编译器。
    然后自己试试记下来就完事了。
    xjr1022
    xjr1022
    OP
    Dec 4, 2018
    22
    @kokutou 没答案,而且卷子连操作系统,编译器版本 c 标准都没指定,估计默认就是谭浩强的那个编译环境了
    misaka19000
    misaka19000
    Dec 4, 2018
    23
    用 gcc 取了下汇编,lea 指令那里看不太懂什么意思,有大佬能解释下吗

    pushq %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq %rsp, %rbp
    .cfi_def_cfa_register 6
    subq $16, %rsp
    movl $2, -4(%rbp)
    movl -4(%rbp), %eax
    leal 1(%rax), %edx
    movl %edx, -4(%rbp)
    movl -4(%rbp), %edx
    movl %eax, %esi
    movl %edx, %edi
    call test
    movl $0, %eax
    freedomSky
    freedomSky
    Dec 4, 2018 via iPhone
    24
    我想知道这是哪儿的考研题
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone
    25
    @misaka19000 #23 lea 实现运算功能,自增 1
    misaka19000
    misaka19000
    Dec 4, 2018
    26
    eax 存的应该是 2,但是不知道 edx 是咋算出来的。。。
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone
    27
    @misaka19000 #23 然后 edi 相当于第一个参数为 3,esi 为第二个参数为 2,结果就是楼主的结果
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone
    28
    @misaka19000 #26 这个代码没优化,讲的啰嗦、其实 edx 就是 lea1(%rax)算的
    misaka19000
    misaka19000
    Dec 4, 2018
    29
    @kljsandjb #25 但是不清楚 rax 的值是多少额,lea 能知道是针对哪一个值进行自增吗
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone
    30
    @misaka19000 #29 rax 不是赋值了吗,先从栈取出来给它的
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone
    31
    @misaka19000 #29 lea 可以做最基本的运算,其实跟地址什么的没什么关系
    XIVN1987
    XIVN1987
    Dec 4, 2018
    32
    TDMGCC:x=3,y=2
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone
    33
    @misaka19000 #29 https://i.loli.net/2018/12/04/5c0650f7e4dae.png 这三行我觉得说得很清楚了呀~
    misaka19000
    misaka19000
    Dec 4, 2018
    34
    @kljsandjb #30 大佬能解释下这行做了什么操作吗

    leal 1(%rax), %edx

    从上下文看这个时候 rax 还没有值吧?
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone
    35
    @misaka19000 #34 eax 是 rax 的低 32 位
    kljsandjb
    kljsandjb
    Dec 4, 2018 via iPhone
    36
    @misaka19000 #34 movl 操作会把高位清零
    misaka19000
    misaka19000
    Dec 4, 2018
    37
    @kljsandjb #36 原来是这样啊,蟹蟹大佬(^ᗜ^)
    Kaiv2
    Kaiv2
    Dec 4, 2018 via Android
    38
    看看汇编,就很清晰了
    GAMEKON
    GAMEKON
    Dec 4, 2018 via Android
    39
    多写一行能死啊
    sbw
    sbw
    Dec 4, 2018❤️2
    40
    ub,取决于编译器实现。

    lea 用于寄存器的时候可以实现简单的 乘 2,乘 4,乘 5,加 1 这种计算,比 add 快(不需要进入 ALU )。
    alaneuler
    alaneuler
    Dec 4, 2018
    41
    这就是 sequence point 吧。。。
    https://en.wikipedia.org/wiki/Sequence_point
    alaneuler
    alaneuler
    Dec 4, 2018❤️1
    42
    Before a function is entered in a function call. The order in which the arguments are evaluated is not specified, but this sequence point means that all of their side effects are complete before the function is entered.
    transzero
    transzero
    Dec 4, 2018 via Android❤️1
    43
    默认 cdecl 调用方式,传参压栈从右往左,++是后计算的,所以第二个 2,第一个自然是 3
    hx1997
    hx1997
    Dec 4, 2018
    44
    国内考研题有的知识那叫一个老旧啊... 这种题也是上世纪谭浩强观念的遗毒,简直让人怀疑他们的知识体系从国外引进来就没有更新过,只会闭门造车......
    iceheart
    iceheart
    Dec 14, 2018 via Android
    45
    这是在写 bug 么?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4249 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 62ms · UTC 06:02 · PVG 14:02 · LAX 22:02 · JFK 01:02
    ♥ Do have faith in what you're doing.