sprintf无法更改printf调用中的静态变量

Rah*_*san 2 c

我似乎无法理解这里到底发生了什么

#include <stdio.h>

const char* mes(int a)
{
    static char mess[100];
    sprintf(mess, "%d", a);
    return mess;
}
const int* hes(int a)
{
    static int arr[100];
    arr[0] = a;
    return arr;
}

int main()
{
    printf("%s %s\n", mes(55), mes(25)); //55 55
    printf("%s\n", mes(55)); //55
    printf("%s\n", mes(25)); //25
    printf("%d %d\n", hes(55)[0], hes(25)[0]); //55 25
}
Run Code Online (Sandbox Code Playgroud)

在第一个printf中,第二个函数似乎被忽略,并且先前输入的输出再次被打印.
起初我认为它是一个静态变量问题,所以我尝试单独打印它们然后它们似乎工作正常.
然后我认为这是一个printf问题所以我试图用整数数组模拟相同的行为,它也在那里工作得很好.
我已经用各种输入运行了这个程序几次,排除了UB的可能性.
那么,我到底错过了什么?

编辑:我在其他地方遇到过这个问题,无法理解发生了什么.所以我用一个简短的示例代码重现了这个问题.但我的问题是,(正如许多人所提到的)是在打印之前评估的所有参数?如果是这样的话,无论评估顺序如何,在两种情况下(int和char数组)都应该有覆盖.

Eug*_*Sh. 5

函数参数的评估顺序是未指定的,这意味着您可以在理论上看到25 25.这是第一件事.其次,当printf被调用时,这两种功能已经被评估,而相同的指针作为第一个和第二个字符串传递(因为它是一个静态的位置),这是最后的评估结果(55你的情况).因此打印相同的文本.

这几乎等同于以下内容:

char* a = mes(25);
char* b = mes(55);

// Note, the above can swap depending on the order of evaluation

printf("%s %s\n", a, b);
Run Code Online (Sandbox Code Playgroud)

但这里a等于b两者都指向一个静态数组.

至于第二个例子,这不会发生,因为它将等同于以下(直到评估顺序):

int *ap = hes(55);
int a = ap[0];

int *bp = hes(25);
int b = bp[0];

printf("%d %d\n", a, b);
Run Code Online (Sandbox Code Playgroud)

注意,这里指向的值是传递的,而不是指针本身.所以即使ap等于bp,a也不一样b.