GCC 前缀递增运算符在将值传递给函数时行为不当

GCC prefix increment operator misbehaving when passing value to the function

当使用 GCC.

编译时,前缀增量运算符在对 printf() 的调用中不发送变量 (x) 的增量值

这是我的代码;

#include <stdio.h>

int bitcount(unsigned);

int main()
{
    unsigned int x = 127;

    printf("bitcount[%d] : %d\n", x, bitcount(x));
    printf("bitcount[%d] : %d\n", ++x, bitcount(x));

    return 0;
}

int bitcount(unsigned int x)
{
    int bitcount = 0;
    for(; x != 0; x >>= 1)
        if( x & 1 )
            bitcount++;

    return bitcount;
}

在 main() 方法中,问题出在下面一行;

printf("bitcount[%d] : %d\n", ++x, bitcount(x));

X 应该增加并发送到 bitcount() 和增加的 x 值。然而,x 的值递增,而不是递增的值,旧值被发送到 bitcount() 函数。

我已经用 MS VS 尝试过同样的事情,但没有发生这种异常行为。输出如下;

在 Windows 10

上使用 GCC 编译的程序输出
D:\C\chapter2>gcc bitcount.c -o bitcount.exe

D:\C\chapter2>bitcount
bitcount[127] : 7
bitcount[128] : 7

在 Windows 10

上使用 MS VS 编译的程序输出
bitcount[127] : 7
bitcount[128] : 1

为确保问题得到解决,我更新了代码以查看发送到函数的值;

Bitcount V2

#include <stdio.h>

int bitcount(unsigned);

int main()
{
    unsigned int x = 127;

    printf("bitcount[%d] : %d\n", x, bitcount(x));
    printf("bitcount[%d] : %d\n", ++x, bitcount(x));

    return 0;
}

int bitcount(unsigned int x)
{
    printf("\nDebug::\tbitcount()::x=%d\n", x);
    int bitcount = 0;
    for(; x != 0; x >>= 1)
        if( x & 1 )
            bitcount++;

    return bitcount;
}

在 Windows 10 系统

上使用 GCC 编译的 Bitcount v2 的输出

调试::位计数()::x=127 位数[127] : 7

调试::位计数()::x=127 位数[128] : 7

很明显,GCC 将 X 的旧值发送给 bitcount() 函数。

为了概括这个问题,我写了下面的程序;

InsideFunc.c

#include <stdio.h>

int func(unsigned);

int main()
{
    unsigned int x = 127;

    printf("x: %d, func(): %d\n",   x, func(x));
    printf("x: %d, func(): %d\n", ++x, func(x));

    return 0;
}

int func(unsigned x)
{
    printf("\n\tDebug::func()::x=%d\n", x);

    return x;
}

在 Windows 10 System

上使用 GCC 编译的输出

D:\C\chapter2>gcc InsideFunc.c -o InsideFunc.exe

D:\C\chapter2>InsideFunc

    Debug::func()::x=127

x: 127, func(): 127

    Debug::func()::x=127

x: 128, func(): 127

同样,变量的值递增,但旧值发送给函数。

这是我的 gcc 版本;

D:\C\chapter2>gcc --version
gcc (GCC) 5.2.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

有什么想法吗?

Late Note : 我刚刚看过 The C Programming Language 一书 Kernighan & Ritchie, 第 49 页,解释了函数参数中的求值顺序是不确定的并且依赖于编译器;

Similarly, the order in which function arguments are evaluated is not specified, so the statement

printf("%d %d\n", ++n, power(2, n)); /*WRONG */

can produce different results with different compilers, depending on whether n is incremented before power is called. The solution, of course, is to write

++n;

printf("%d %d\n", n, power(2, n));

在 C++ 中未指定函数调用参数的求值顺序,因此行:

printf("bitcount[%d] : %d\n", ++x, bitcount(x));

无法保证 ++x 会在 bitcount(x) 之前计算,因此 bitcount 可能会通过 x 预递增。您所有的编译器都有不同但有效(即符合标准)的行为。

不要在表达式中使用递增:

printf("bitcount[%d] : %d\n", x, bitcount(x));
x++;
printf("bitcount[%d] : %d\n", x, bitcount(x));