2

これが私のコードです:

void func(char c)
{
    char * ptr = &c;
    size_t len = strlen(ptr);
    printf("len - %d\n", len);
}

lenは常に 1 として出力されます。

strlen(..)配列の最後にcharあるヌル文字 ( ) を見つけることによって、配列の長さを決定します。\0ここでptrは、1 文字 ( c) のアドレスだけで初期化されます。cnull 文字が含まれていません。長さはどのようにptr取得しますか?

4

3 に答える 3

7

strlen()null で終わる配列を指していないポインターでは使用できません。未定義の動作を引き起こします。

プログラムが UB に達すると、何も保証されません。

FWIWstrlen()は type を返すため、フォーマット指定子をsize_t使用して結果を出力する必要があります。%zu

于 2016-02-18T09:39:08.903 に答える
4

コードの動作は、 2 つの点で未定義です。誤って 1 を返します。

  1. strlen指定されたアドレスから開始し、 に達するまでそのアドレスをインクリメントすることによって機能します\0。これは、C 標準ライブラリが文字列をモデル化する方法と一致しています。開始アドレスとそれの間のすべてのメモリを(連続したブロックとして)所有していない場合、\0への入力strlenは不正な形式です。

  2. printf形式指定子が正しくないため、の動作は未定義です。に使用%zusize_tます。

于 2016-02-18T09:40:49.050 に答える
0

c にはヌル文字が含まれていません。ptr はどのように長さを取得しますか?

そうではありません。のアドレスに続くメモリ位置にcたまたまゼロバイトが含まれているため、テストで正しい答えが得られたようです。この場所はゼロを含むように定義されておらず、プログラムがそれにアクセスすることも許可されていないため、そのようなコードが機能し続けるとは期待できません。

C 標準の言語では、プログラムの動作はundefinedです。つまり、演算の結果が予測できないだけでなく、プログラム全体が無意味になります。

未定義の動作を考慮しなくても、上記のコードはわずかな変更で動作しなくなる可能性があります。たとえば、アーキテクチャ、コンパイラ、またはコンパイル フラグを変更した場合、またはミックスに関数を追加した場合などです。このようなコード スニペットは、内部でどのように機能するかを知るのに役立ちますが、運用コードでは決して使用しないでください。

于 2016-02-18T09:42:11.907 に答える