web-dev-qa-db-ja.com

文字列リテラルで記号\ 0はどういう意味ですか?

次のコードを検討してください。

char str[] = "Hello\0";

Str配列の長さはどのくらいですか?また、0で終わるのは何ですか?

49
UmmaGumma

sizeof strは7-「Hello」テキストの5バイト、明示的なNULターミネータ、および暗黙的なNULターミネータです。

strlen(str)は5-5つの「Hello」バイトのみです。

ここで重要なのは、暗黙のNULターミネーターがalwaysが追加されていることです-文字列リテラルがたまたま\0で終わっている場合でも。もちろん、strlenは最初の\0で停止します-違いはわかりません。

暗黙的なNULターミネータールールには1つの例外があります。配列サイズを明示的に指定すると、文字列は収まるように切り捨てられます。

char str[6] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 6 (with one NUL)
char str[7] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 7 (with two NULs)
char str[8] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 8 (with three NULs per C99 6.7.8.21)

ただし、これはめったに有用ではなく、文字列の長さを誤って計算し、終了しない文字列で終わる傾向があります。 C++では禁止されています。

86
bdonlan

配列の長さは7で、NUL文字\0は引き続き文字としてカウントされ、文字列は暗黙的な\0で終了します

this link をご覧ください。

strchar str[6]= "Hello\0";として宣言した場合、暗黙のNULは適合する場合にのみ追加されるため、長さが6になることに注意してください(この例では不可能です)。

§6.7.8/p14
文字型の配列は、文字列リテラルで初期化できます。オプションで中括弧で囲むことができます。文字列リテラルの連続文字(終端のヌル文字に余裕がある場合または配列のサイズが不明な場合を含む)配列の要素を初期化する。

char str[] = "Hello\0"; /* sizeof == 7, Explicit + Implicit NUL */
char str[5]= "Hello\0"; /* sizeof == 5, str is "Hello" with no NUL (no longer a C-string, just an array of char). This may trigger compiler warning */
char str[6]= "Hello\0"; /* sizeof == 6, Explicit NUL only */
char str[7]= "Hello\0"; /* sizeof == 7, Explicit + Implicit NUL */
char str[8]= "Hello\0"; /* sizeof == 8, Explicit + two Implicit NUL */
10
SiegeX

具体的には、混乱する可能性のある1つの状況に言及したいと思います。

「\ 0」と「」の違いは何ですか?

答えは、"\0"は配列で{0 0}を表し、""{0}であるということです。

"\0"は依然として文字列リテラルであり、末尾に"\0"も追加されるためです。 ""は空ですが、"\0"も追加します。

これを理解すると、"\0"を深く理解するのに役立ちます。

5
YongHao Hu

JUST TRY ITの私の通常のドラムソロを叩いて、今後そのような質問に答えることができます。

$ cat junk.c
#include <stdio.h>

char* string = "Hello\0";

int main(int argv, char** argc)
{
    printf("-->%s<--\n", string);
}
$ gcc -S junk.c
$ cat junk.s

...不要な部分を取り除く...

.LC0:
    .string "Hello"
    .string ""

...

.LC1:
    .string "-->%s<--\n"

...

ここで、printfに使用した文字列が"-->%s<---\n"であるのに対し、グローバル文字列は"Hello"""の2つの部分にあることに注意してください。 GNUアセンブラーは、暗黙のNUL文字でストリングを終了するため、最初のストリング(.LC0)がこれらの2つの部分にあるという事実は、2つのNULがあることを示します。したがって、文字列の長さは7バイトです。一般に、コンパイラが特定のコードの塊で何をしているのか本当に知りたい場合は、このようなダミーの例でそれを分離し、-S(GNU-MSVCアセンブラー出力用のフラグもありますが、私はそれをオフハンドで知りません)。コードがどのように機能するか(または場合によっては機能しない)について多くのことを学習し、作業中のツールと環境に完全に一致することが100%保証された回答がすぐに得られます。

Str配列の長さはどのくらいですか?また、0で終わるのは何ですか?

調べてみましょう:

int main() {
  char str[] = "Hello\0";
  int length = sizeof str / sizeof str[0];
  // "sizeof array" is the bytes for the whole array (must use a real array, not
  // a pointer), divide by "sizeof array[0]" (sometimes sizeof *array is used)
  // to get the number of items in the array
  printf("array length: %d\n", length);
  printf("last 3 bytes: %02x %02x %02x\n",
         str[length - 3], str[length - 2], str[length - 1]);
  return 0;
}
3
Fred Nurk
char str[]= "Hello\0";

それは7バイトになります。

メモリ内では次のようになります。

48 65 6C 6C 6F 00 00
H  e  l  l  o  \0 \0

編集:

  • C文字列で\ 0記号は何を意味しますか?
    これは文字列の「終わり」です。ヌル文字。メモリでは、実際にはゼロです。通常、char配列を処理する関数は、この文字を探します。これはメッセージの終わりです。最後に例を示します。

  • Str配列の長さは? (編集部分の前に回答)
    7

  • そして、どのくらいの0で終わるのですか?
    配列には、ゼロのある2つの「スペース」があります。 str [5] = str [6] = '\ 0' = 0

追加の例:
そのテキスト配列の内容を出力する関数があると仮定しましょう。次のように定義できます。

char str[40];

これで、「これは単なる印刷テストです」というメッセージが含まれるように、その配列の内容を変更することができます(方法について詳しくは説明しません)。

54 68 69 73 20 69 73 20 6a 75 73 74 20 61 20 70 72 69 6e 74
69 6e 67 20 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00

したがって、そのchar配列を出力します。そして、あなたは新しいメッセージが欲しいです。 「こんにちは」とだけ言ってみましょう

48 65 6c 6c 6f 00 73 20 6a 75 73 74 20 61 20 70 72 69 6e 74
69 6e 67 20 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00

Str [5]の00に注目してください。これは、ベクトルとコンテンツ全体の実際の経度にもかかわらず、印刷関数が実際に送信する必要がある量を知る方法です。

0
L. Lopez