4

C ポインターの文献で C のスキルを磨こうとしているときに、このコードに出くわしました。この問題では、出力を正当化することになっています。strcat()との作業に精通していstrcmp()ます。strcmp()渡された 2 つの文字列が同じ場合、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 です。これは、計算された 2 つの文字列が同じでなければならないことを意味します。複数のステップでステートメントを解決しようとしました。

まず、試してみstrcat(str3, strcpy(str2, str1))ました。「str2」は「Good」に変更され、次に「DayGood」にstrcat()変更されます。str3これまでのところ、私の gcc コンパイラーは私と同意見です。

になるstrcat(str3, "good")と、str3 はDayGoodすでに にstrcat変更されているため、 に変更str3されDayGoodgoodます。

繰り返しますが、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

両方のテスト ケースで、比較のために 2 つの異なる文字列を取得します。なぜstrcmp()0 を生成するのですか?

4

6 に答える 6

3

すべての呼び出しをトレースせずに答えを取得する簡単な方法があります: への両方の引数がs から最初の arg とともに返され、最初の argがstrcat返されるため、最終的な呼び出しは当然 0 になることを意味します。その上で操作が行われました。strcpystr3strcpystrcmp(str3, str3)

更新された質問への回答として、これを試して、悟ったかどうかを確認してください。

#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 に割り当てられたメモリ アドレスと同じものを返します。したがって、変数 str3 をそれ自体と比較しているため、strcmp は 0 を返します。

于 2013-07-27T21:50:20.850 に答える
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 に答える