1

次のように表示されるテストを作成しました。

char* trim(char* strr, char* str1) {
  char* s = strr;
  while(*str1 == 32) str1++;
  while( (*str1 != 32) && (*str1 != 0) )
        *s++ = *str1++;
  *s = 0;
  return strr;
  }

int main(void) {
  char str[20] = "???";
  char str1[20] ="    bcd  \0";

  printf("(%s)\n(%s)\n", str, trim(str, str1));
  return(0);
}

質問は、上記のコードは何を出力し、その理由は何ですか? 出力とその理由についての手がかりを得ましたが、この件に関してより経験豊富な人々から聞きたいと思います.

一見すると、次のように表示されます。

(???)
(bcd)

しかし実際には、生成される出力は次のとおりです。

(bcd)
(bcd)
4

3 に答える 3

2

[編集: 以前の回答を削除しました。@Nigel Harper は、完全にナンセンスであると丁寧に指摘してくれました。]

printf(すべての引数)への引数は、printfそれ自体の実行が開始される前に、特定されていない順序で評価されます。したがって、printf実行が開始されるまでに、strと (重要なことに)の両方trim(str, str1)が評価されます。

が指し示すtrim(str, str1)メモリを変更するため、それ自体が実行されるまでに、will が指すメモリは変更されて、(もちろん、will から返されたポインタも) が含まれるようになります。strprintfstrbcdtrim(str, str1)

したがって、2 つの引数が評価される順序に関係なく、両方の出力は になりますbcd

于 2013-04-09T23:50:23.270 に答える
1

呼び出しで str である関数内で strr に上書きしています。参照によって渡されるため、変更は呼び出し元の関数に反映されます。printf は str の評価されたコピーを取得します (両方の引数で同じ)。

于 2013-04-09T23:53:06.067 に答える
0

最後の引数が最初に評価され、最初にスタックにプッシュされます。しかし、引数を評価する順序は明確ではありません。

簡単なコードを作成しました:

#include <stdio.h>

char *go(char *s) { *s = '0'; return s; }

int main() {
    char str[] = "xyz", str1[] = "abc";
    printf("(%s)(%s)\n", str, go(str));
    printf("(%s)(%s)\n", go(str1), str1);
}

出力:

(0yz)(0yz)
(0bc)(0bc)

次の gcc コマンド ラインを使用して、アセンブリの出力を分析できます。

gcc -c -g -Wa,-a,-ad x.c >x.lst

-O2 を追加すると、順序は同じですが、go() 関数がインライン化されます。

うーん...私はまた何かを学びました! ありがとう!

于 2013-04-09T23:53:39.673 に答える