6

null char ('\0', 0) を %s で出力すると、実際に "(null)" 文字列が出力されるのはなぜですか?

このコードのように:

char null_byte = '\0';
printf("null_byte: %s\n", null_byte);

...印刷:

null_byte: (null)

...そしてそれはValgrindの下でもエラーなしで実行されます.私が得るのはコンパイラの警告warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]だけです(注:私は32ビットUbuntuでgcc 4.6.3を使用しています)

4

6 に答える 6

10

これは未定義の動作ですが、実装では次のことが起こります。

  • int渡す 0の値は%s、null ポインターとして読み取られます
  • %sbyの処理にはprintf、null ポインターを識別して print する特殊なケースのコードがあります(null)

どちらも標準では必要ありません。[*] 必要な部分はchar、varargs で使用される a が として渡されることintです。

[*] 実装で のすべての値をcharとして表すことができることを考えると、それは必須ですintcharが符号なしで と同じ幅である面白い実装を使用している場合int、 として渡されunsigned intます。面白い実装は標準に準拠すると思います。

于 2012-12-03T10:32:50.807 に答える
4

まず第一に、あなたのやり方は間違っています。'\0'は文字であり%c、 ではなくで印刷する必要があり%sます。これが実験目的で意図的に行われたかどうかはわかりません。

の実際のバイナリ値は\00 です。値 0 をchar *ポインターにキャストしようとしていますが、無効な参照とクラッシュが発生します。あなたのコンパイラは、値の特別な扱いでそれを防いでい%sます。

ソースコードではなく、結果のバイナリで実行されるため、Valgrind はそれをキャッチしません (代わりに静的アナライザーが必要です)。コンパイラはすでにその呼び出しを安全な「null ポインタ」テキストに変換しているため、valgrind は問題を認識しません。

于 2012-12-03T10:34:11.837 に答える
1

null_byteには0が含まれています。printfで%sを使用すると、char(char *)のアドレスである文字列を出力しようとしています。コードで行うことは、文字列のアドレスとしてアドレス0(NULL)を渡すことです。これが、出力がnullである理由です。コンパイラは、%s修飾子に間違った型を渡したと警告しました。printf( "null_byte:%s \ n"、&null_byte);を試してください。

于 2012-12-03T10:36:29.567 に答える
0

printfステートメントは文字列を出力しようとしているため、値が null の値として解釈されますnull_byechar *警告に注意してください。これを行うか

printf("null_byte: %s\n", &null_byte);

またはこれ

printf("null_byte: %c\n", null_byte);
于 2012-12-03T10:33:31.140 に答える
0

は可変長であるためprintf、通常の引数昇格が実行され、値null_byteに昇格 (キャスト) されます。int0

printfchar *次にポインターを読み取り、 0int は null ポインターとして解釈されます。C 標準ライブラリには、null 文字列が として出力される機能があります(null)

于 2012-12-03T10:34:42.383 に答える