4

在我使用 C 指针文献来磨练我的 C 技能的过程中,我遇到了这段代码。在这个问题中,我应该证明输出的合理性。我熟悉 和 的strcat()工作strcmp()。我知道strcmp()当两个字符串通过时返回 0 是相同的。

# include <stdio.h>
# include <string.h>
int main()
{
    static char str1[]="Good";
    static char str2[20];
    static char str3[20] ="Day";

    int l;      

    l = strcmp(strcat(str3, strcpy(str2, str1)), strcat(str3, "good"));

    printf("%d\n", l);
    return 0;
}

提供的答案是 0,这意味着两个计算的字符串必须相同。我试图通过多个步骤解决该语句。

首先,试过了strcat(str3, strcpy(str2, str1))。'str2' 变为“Good”,然后strcat()变为str3“DayGood”。到目前为止,我的 gcc 编译器同意我的看法。

来到strcat(str3, "good"),由于 str3 已更改为DayGoodstrcat更改str3DayGoodgood

再次,gcc 与我争吵。

int main()
{
    static char str1[]="Good";
    static char str2[20];
    static char str3[20] ="Day";

    int l;
    printf("%s\n", strcat(str3, strcpy(str2, str1)));
    printf("%s\n", strcat(str3, "good"));       

    //l = strcmp(strcat(str3, strcpy(str2, str1)), strcat(str3, "good"));

    //printf("%d\n", l);
    return 0;
}

它产生

DayGood

DayGoodgood

我再次尝试了这种变化。

int main()
{
    static char str1[]="Good";
    static char str2[20];
    static char str3[20] ="Day";

    int l;

    printf("%s\n", strcat(str3, "good"));
    printf("%s\n", strcat(str3, strcpy(str2, str1)));

    //l = strcmp(strcat(str3, strcpy(str2, str1)), strcat(str3, "good"));

    //printf("%d\n", l);
    return 0;
}

它产生。

Daygood
DaygoodGood

在我的两个测试用例中,我得到了两个不同的字符串进行比较。那么为什么会strcmp()产生一个 0 ?

4

6 回答 6

3

有一种无需跟踪所有调用即可快速获得答案的方法: 的两个参数strcat都从strcpys 返回第一个 arg str3,并且由于strcpy返回其第一个 arg,这意味着最终调用strcmp(str3, str3)当然是 0 不管多么奇怪已经对其进行了操作。

针对更新的问题,试试这个,看看你是否得到启发:

#include <stdio.h>
#include <string.h>
int main(void)
{
    static char str1[]="Good";
    static char str2[20];
    static char str3[20] ="Day";
    char *first, *second;

    printf("str3 = %p => %s\n", (void *)str3, str3);

    first = strcat(str3, strcpy(str2, str1));
    printf("first strcat returned %p => %s\n", (void *)first, first);
    printf("and now str3 = %p => %s\n", (void *)str3, str3);

    second = strcat(str3, "good");
    printf("second strcat returned %p => %s\n", (void *)second, second);
    printf("and now first = %p => %s\n", (void *)first, first);
    printf("and now str3 = %p => %s\n", (void *)str3, str3);

    printf("Is it any surprise that strcmp(first,second) = %d?\n",
        strcmp(first,second));
    return 0;
}
于 2013-07-27T21:47:08.800 回答
3

无论编译器选择哪种顺序来计算 的参数strcmpstrcat总是返回它的第一个参数。

因此,本质上会发生以下情况:

... // execute strcat(str3, strcpy(str2, str1)) and strcat(str3, "good")
l = strcmp(str3, str3);
于 2013-07-27T21:47:33.220 回答
2

它返回 0 因为两个参数:

strcat(str3, strcpy(str2, str1))

strcat(str3, "good")

实际上返回相同的东西:分配给 str3 的内存地址。因此,strcmp 返回 0,因为它正在将变量 str3 与自身进行比较。

于 2013-07-27T21:50:20.850 回答
1

strcmp gets two pointers to strings as its arguments:

 l = strcmp(strcat(str3, strcpy(str2, str1)), strcat(str3, "good"));

1st step:

l = strcmp(str3, strcat(str3, "good"));

Here str3 points to the string DayGoodgoodGood.

2nd step:

 l = strcmp(str3,str3 );

Now str3 points to the string DayGoodgoodGoodgood.

This will return 0 no matter what str3 points to. Since addresses are same strcmp shouldn't even compare for optimization; just returns 0.

于 2013-07-27T22:17:05.090 回答
1

strcat始终返回传递给它的第一个参数的事实使您的表达式始终为真。这是解释:

strcmp(strcat(str3, strcpy(str2, str1)), strcat(str3, "good"));
//            ^^^^                              ^^^^

// become

strcmp( str3, str3 );

因此,通过将变量与自身进行比较来strcmp返回。0

你应该知道这种表达方式不是很好,因为它使代码更难理解,并且可能导致未定义的行为比你想象的更快......

于 2013-07-27T21:51:23.337 回答
0

strcat返回它的第一个参数,这就是为什么!

于 2013-07-27T21:50:59.480 回答