6

strcpy の使用について質問があります。ANSI C 規格に次のように書かれていることは知っています。Linux で古い gnu C コンパイラを使用してコンパイルした場合に期待どおりに動作するコードを示します。

#include <string.h>
#include <stdio.h>

char S[80],*P;

int main() {
    strcpy(S,"abcdefghi\r\njklmnopqr\r\nstuvwxyz\r\n");
    for (P=S; P=strchr(P,'\r'); P++) strcpy(P,P+1);
    printf("%s\n",S);
    return 0;
}

\rこのシーケンスは、入力文字列からすべての (キャリッジ リターン) を削除します。strcpy の非常に単純な実装は次のとおりであることを (Kernigham と Ritchie から) 知っています。

while (*t++=*s++) ;

ここで、gcc (Gentoo 4.5.4 p1.0, pie-0.4.7) 4.5.4 を使用してプログラムをコンパイルすると、次のように出力されます。

abcdefghi
jklmnpqr          <-- missing 'o'
stuvwxxyz         <-- doubled 'x'

このコンパイラ (実際にはそのライブラリ) は に対して非常に洗練されたシーケンスを使用しているstrcpyと思いますが、その理由はわかりません。

4

2 に答える 2

13

あなたはそれをしないように警告されました。その理由は、バイト単位のコピーは実際には非常に遅く、文字列を通過するために多くのループを必要とするためです。コンパイラーはこれを簡単に最適化できます(たとえば、int一度にサイズのチャンクをコピーするか、プラットフォーム固有の並列化を使用します)。

ただし、文字列が重複している場合、これらの最適化により、データに関する仮定が無効になります。結果として、それらはあなたに不特定の結果を与えます。古いGCCがそのような最適化を行っていない可能性があります。

のドキュメントにstrcpy()は重複する文字列を使用しないように記載されているため、使用しないでください。

于 2012-10-17T13:29:19.203 に答える
2

実装が何をしているかを把握する最善の方法は、もちろんそのライブラリのソースを読むことです。

ソースが利用できない場合、次善の選択肢は、コンパイラが生成する生成されたアセンブリ コードを読み取ることです。

また、ライブラリの「本格的な」オープン ソース実装を見て、そこから何らかの結論を導き出すこともできます。

1 つの考えとしては、ライブラリが一度に 1 文字よりも大きなチャンクでデータをコピーしている可能性があります。これは、設計上の前提に違反すると壊れます。

于 2012-10-17T13:28:48.100 に答える