[解決済み] char *とchar[]の違い [重複]
質問
多くのスレッドや質問を読み、多くの回答を読みましたが、まだ違いを理解することが難しく、いつ何を使うべきなのか?
データを保存する必要があり、動的であるためサイズがわからない場合は、char*を使用するべきだと思います。 また、正しいかどうかわかりませんが、私の理解では、char*を宣言し、それにリテラルテキストを代入すると、次のようになります。 char *ch = "hi"; これは変更できない定数で、もし変更しようとすると、新しい文字列を格納した別のメモリ空間をchに指定するだけなのでしょうか? このように書くと: char ch = malloc(20); とすれば、値を変更することができます。 とすると、こうなります。 char ch[] = "ハイ"。 char pch = ch; を指すと、配列はch[0]を指すので、値も同様に変更できるのですね?
太字で書かれたものはすべて私が読んで理解したものです。しかし、おそらく私が今言ったことのほとんどについて間違っていると思いますので、違いを理解し、いつ何を使うべきかを一度で理解するために、本当に良くて簡単な説明が必要です。
EDIT :
#include <stdio.h>
main()
{
char ch[] = "Hello";
char *p1 = ch;
char *p2 = p1;
char *p3 = *p1;
printf("ch : %s\n", ch);
printf("p1 address [%d] value is %s\n", p1, *p1);
printf("p2 address [%d] value is %s\n", p2, *p2);
printf("p3 address [%d] value is %s\n", p3, *p3);
return 0;
}
解決方法は?
一番わかりやすい答えは
<ブロッククオートここでの違いは
char *s = "Hello world";
は、Hello worldをメモリの読み出し専用部分に置き、その上に へのポインタとなり、このメモリへの書き込み操作ができなくなります。 は違法です。しながら
char s[] = "Hello world";
は、リテラル文字列を読み取り専用メモリに置き、その文字列を スタック上に新たに確保されたメモリ。このように
s[0] = 'J';
を合法化します。
もっと長く説明すると、メモリがどのセグメントに格納されているのか、どれくらいのメモリが割り当てられているのか、などです。
Example: Allocation Type: Read/Write: Storage Location: Memory Used (Bytes):
===========================================================================================================
const char* str = "Stack"; Static Read-only Code segment 6 (5 chars plus '\0')
char* str = "Stack"; Static Read-only Code segment 6 (5 chars plus '\0')
char* str = malloc(...); Dynamic Read-write Heap Amount passed to malloc
char str[] = "Stack"; Static Read-write Stack 6 (5 chars plus '\0')
char strGlobal[10] = "Global"; Static Read-write Data Segment (R/W) 10
参考文献
-
C言語のchar s[]とchar *sの違いは何ですか?
, アクセス数 2014-09-03,
<https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c>
-
宣言文字列と割り当て文字列の違い
, アクセス数 2014-09-03,
<https://stackoverflow.com/questions/16021454/difference-between-declared-string-and-allocated-string>
編集
質問と一緒に出されたコメントの編集に対応するために、あなたの解決策にメモを追加しました。
#include <stdio.h>
int main() {
char ch[] = "Hello"; /* OK; Creating an array of 6 bytes to store
* 'H', 'e', 'l', 'l', 'o', '\0'
*/
char *p1 = ch; /* OK; Creating a pointer that points to the
* "Hello" string.
*/
char *p2 = p1; /* OK; Creating a second pointer that also
* points to the "Hello" string.
*/
char *p3 = *p1; /* BAD; You are assigning an actual character
* (*p1) to a pointer-to-char variable (p3);
* It might be more intuitive if written in
* 2 lines:
* char* p3;
* p3 = *p1; //BAD
*/
printf("ch : %s\n", ch); /* OK */
printf("p1 address [%d] value is %s\n", p1, *p1); /* Bad format specifiers */
printf("p2 address [%d] value is %s\n", p2, *p2); /* Bad format specifiers */
printf("p3 address [%d] value is %s\n", p3, *p3); /* Bad format specifiers */
return 0;
}
では、3つの大きなバグを。
-
を割り当てている。
char
の値をpointer-to-char
という変数があります。コンパイラはこのことについて警告しているはずです。(char *p3 = *p1
). -
お使いのコンパイラによっては、ポインタ
%p
フォーマット指定子ではなく、アドレスを出力するための%d
(整数)形式指定子。 -
あなたが使っているのは、文字列
%s
指定子でchar
のデータ型(例.printf("%s", 'c')
は誤りです)。一文字を印刷する場合は%c
また、マッチする引数は文字でなければなりません (例: 'c', char b, など)。文字列全体を表示する場合は、書式指定子として%s
形式指定子で、引数は ポインタ-文字 .
例
#include <stdio.h>
int main(void) {
char c = 'H'; // A character
char* pC = &c; // A pointer to a single character; IS NOT A STRING
char cArray[] = { 'H', 'e', 'l', 'l', 'o' }; // An array of characters; IS NOT A STRING
char cString[] = { 'H', 'e', 'l', 'l', 'o', '\0' }; // An array of characters with a trailing NULL charcter; THIS IS A C-STYLE STRING
// You could also replace the '\0' with 0 or NULL, ie:
//char cString[] = { 'H', 'e', 'l', 'l', 'o', (char)0 };
//char cString[] = { 'H', 'e', 'l', 'l', 'o', NULL };
const char* myString = "Hello world!"; // A C-style string; the '\0' is added automatically for you
printf("%s\n", myString); // OK; Prints a string stored in a variable
printf("%s\n", "Ducks rock!"); // OK; Prints a string LITERAL; Notice the use of DOUBLE quotes, " "
printf("%s\n", cString); // OK; Prints a string stored in a variable
printf("%c\n", c); // OK; Prints a character
printf("%c\n", *pC); // OK; Prints a character stored in the location that pC points to
printf("%c\n", 'J'); // OK; Prints a character LITERAL; Notice the use of SINGLE quotes, ' '
/* The following are wrong, and your compiler should be spitting out warnings or even not allowing the
* code to compile. They will almost certainly cause a segmentation fault. Uncomment them if you
* want to see for yourself by removing the "#if 0" and "#endif" statements.
*/
#if 0
printf("%s\n", c); // WRONG; Is attempting to print a character as a string, similar
// to what you are doing.
printf("%s\n", *pC); // WRONG; Is attempting to print a character as a string. This is
// EXACTLY what you are doing.
printf("%s\n", cArray); // WRONG; cArray is a character ARRAY, not a C-style string, which is just
// a character array with the '\0' character at the end; printf
// will continue printing whatever follows the end of the string (ie:
// random memory, junk, etc) until it encounters a zero stored in memory.
#endif
return 0;
}
コード一覧 - 提案された解決策
#include <stdio.h>
int main() {
char ch[] = "Hello"; /* OK; Creating an array of 6 bytes to store
* 'H', 'e', 'l', 'l', 'o', '\0'
*/
char *p1 = ch; /* OK; Creating a pointer that points to the
* "Hello" string.
*/
char *p2 = p1; /* OK; Creating a second pointer that also
* points to the "Hello" string.
*/
char *p3 = p1; /* OK; Assigning a pointer-to-char to a
* pointer-to-char variables.
*/
printf("ch : %s\n", ch); /* OK */
printf("p1 address [%p] value is %s\n", p1, p1); /* Fixed format specifiers */
printf("p2 address [%p] value is %s\n", p2, p2); /* Fixed format specifiers */
printf("p3 address [%p] value is %s\n", p3, p3); /* Fixed format specifiers */
return 0;
}
サンプル出力
ch : Hello
p1 address [0x7fff58e45666] value is Hello
p2 address [0x7fff58e45666] value is Hello
p3 address [0x7fff58e45666] value is Hello
関連
-
警告:代入がキャストなしで整数からポインタを作成する場合の修正方法に関する警告
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] なぜパスワードにはStringではなくchar[]が好まれるのですか?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] 配列の場合、なぜ a[5] == 5[a] になるのでしょうか?
-
[解決済み] const int*、const int * const、int const *の違いは何ですか?
-
[解決済み] C言語でランダムなint型を生成するには?
-
[解決済み] char s[]とchar *sの違いは何ですか?
-
[解決済み] C言語でファイルサイズを取得するには?[重複]する
-
[解決済み】C/C++の"-->"演算子とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Code::Blocks アプリケーションをコンパイルできない
-
[解決済み] munmap_chunk(): 無効なポインタ
-
[解決済み] "static const" vs "#define" vs "enum"
-
[解決済み] Cコードの単体テスト【終了しました
-
[解決済み] プログラム終了前にmallocの後にfreeをしないと本当に何が起こるのか?
-
[解決済み] longをフォーマットするprintfの引数は何ですか?
-
[解決済み] char s[]とchar *sの違いは何ですか?
-
[解決済み] フリーは、どのように無料化を知っているのですか?
-
[解決済み] ストラクチャーとユニオンの違い
-
[解決済み] C言語でファイルサイズを取得するには?[重複]する