答えて
それぞれは、(少なくとも概念的には)読み取り専用の静的メモリで文字列リテラルを作成するよう強制します。
最初は、それを使って配列の内容を初期化します。文字列リテラルは、サイズを選択して初期化するために使用されます。
2番目の文字列は、元の文字列リテラルに直接ポインタを作成します。
これらの間には、本当に良いことも悪いこともありません。彼らはただ違っている。たとえば、配列は通常、より多くのメモリを使用します(文字列リテラルがあり、配列内に文字列リテラルの完全なコピーがあります)。ただし、そうでなければ通常の配列なので、必要に応じて変更することができます。
文字列リテラルへのポインタは、しばしばメモリを節約します。また、異なる値をポインタに代入して、異なる時間に異なる文字列リテラルを指すようにすることもできます。しかしではなくですが、それが指すデータを変更することができます。そうすることで、未定義の動作が得られます。
2つは同じように見えますが、しばしば互換的に使用されますが、異なる意味を持ちます。最初の行:
... NULターミネーターを含め、文字列リテラルを保持するのに十分な大きさの配列を作成します。この配列は、指定した文字列リテラルで初期化されます。このバージョンの利点の1つは、アレイを後で変更できることです。また、配列のサイズはコンパイル時でもわかりますので、sizeof
演算子を使用してそのサイズを決定することができます。
printf("%u\n",unsigned(sizeof(a))); // Will display 15, which is the array's size
// including the NUL terminator
二行目:例えば
char *p = "string literal";
...だけリテラル文字列を指すようにポインタを設定します。これは最初のバージョンよりも速いですが、リテラルが変更されてはならないという欠点があります。これは、読み取り専用としてマークされたページに存在する可能性があるためです。文字列の長さを知るには関数を使う必要があるという欠点もあります。sizeof
演算子はポインタ変数のサイズを与えるだけであるからです。例:
printf("%u\n",unsigned(sizeof(p))); // Will likely display 4 or 8, depending on
// whether this is a 32-bit or 64-bit build
printf("%u\n",unsigned(strlen(p))); // Will display the correct length of 14, not
// including the NUL terminator
これらの変数は、これらの変数でどのような処理を行うかによって異なります。文字列を変更する必要がない場合は、をに変更して、char *
をconst char *
に変更します。誤って指定した文字に変更を加えないでください。データを変更する予定がある場合は、以前のアレイベースのバージョンを使用して、初期化後にアレイを変更できるようにします。
2番目の例で 'char const *'を使用する方が実際には賢明ですが、コンパイラは標準で後方互換性のある疣贅のために 'char *'バージョンを受け入れることを義務付けられています。 –
@larsmans、私はより完全にするために私の答えにこの事実を追加しました。ありがとう... –
答えにC++出力の例を追加したことがありますが、OPはそれにラベルを付けました。 –
必要なものによって異なります。
char a[] = "string literal";
自動記憶寿命可変文字列を作成します。これは合法です:一方
a[0] = 'c';
...
char *p = "string literal";
がメモリを読み取り専用にするポインタを作成します。宣言は本当にあなたが合法的にどのようなp
ポイントを変更することはできません
const char *p = "string literal";
でなければなりません。
最初に配列を宣言して記入します(要素を1つずつ設定し、最後のnullバイトが含まれるまで)。配列は変更できます。
第2はポインタを宣言し、それを定数リテラルに設定して入力します。ポインターを変更することができます(たとえば、他の場所を指すようにすることもできます)が、指し示す定数ストリング(ほとんどのシステムでは読み取り専用セグメントに入れられます)を変更することはできません。
1つは指定したデータでいっぱいの配列を与え、2つ目は指定したデータを含むどこかのメモリ(通常は読み取り専用)へのポインタを与えます。
より明確に「あなたは何を得る」の違いを確認するには、これを試してみてください。ここで
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char a[] = "string literal";
char *b = "string literal";
printf("a is %lu bytes, b is %lu\n", (unsigned long) sizeof a,
(unsigned long) sizeof b);
return EXIT_SUCCESS;
}
は、上記のコードでlive demoです。
- 1. ここで文字列を分割する良い方法は何ですか?
- 2. 文字列大文字 - 良い方法
- 3. SKAudioNodeの差異のinit(fileNamed:文字列)のinit間(URL:URL)
- 4. C#は、私はそれでキャリッジリターンと文字列が文字列
- 5. この文字列に隠れた文字は何ですか?
- 6. initメソッドは構文砂糖を持つinit配列ですか?
- 7. この良いC#スタイルですか?
- 8. それはここでは、文字列
- 9. C#で。文字列と文字列の違いは何ですか?
- 10. 長い文字列から文字列を解析する最も良い方法は何ですか?
- 11. UIActionSheet varargs initメソッドに文字列の配列を送信するにはどうすればよいですか?
- 12. 文字列内の任意の数字の文字列をチェックする良い方法はありますか?
- 13. メモリ効率が良い、SQLiteデータベースかXML文字列[]ですか?
- 14. C++チュートリアルで文字列の配列が文字列に使用されているのはなぜですか?
- 15. 文字列から文字列を構築する最も良い方法
- 16. javascript文字列からこれらの文字を削除する最も良い方法
- 17. これは私の文字列である文字列内
- 18. 文字列または文字配列のインデックスを取得する最も良い方法は何ですか?
- 19. Cの文字配列から文字列を取得するにはどうすればよいですか?
- 20. 文字列をPHPでUnicode文字の配列に分割する最も良い方法は何ですか?
- 21. ここでは、文字列
- 22. 文字列はここで
- 23. C#で文字列をPascalCase文字列に変換するにはどうすればよいですか?
- 24. Java:文字列はいつ文字列constプールに入りますか?ここ
- 25. は、文字列を手に入れた、ここではその文字列
- 26. 文字列リテラルを使って文字の配列を初期化する方が良いですか?
- 27. これはC++でポインタを使う良い方法ですか?
- 28. なぜこの文字列トークンは文字列にキャストされますか?
- 29. 文字列関数のより良いjavascriptですか?
- 30. この文字配列パラメータをCからC#の文字列にマーシャリングするにはどうすればよいですか?
重複:stackoverflow.com/questions/7886972/difference-between-char-and-char – tinman
これが何度も尋ねられた場合、人々はなぜ閉じるのではなく答えるのですか? – sidyll
@sidyll:人々は重複をチェックするのではなく、担当者を得るために質問に答えます。 – tinman