1. ホーム
  2. c

[解決済み] char *とchar[]の違い [重複]

2022-03-14 15:06:48

質問

多くのスレッドや質問を読み、多くの回答を読みましたが、まだ違いを理解することが難しく、いつ何を使うべきなのか?

データを保存する必要があり、動的であるためサイズがわからない場合は、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

参考文献


  1. 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>
  2. 宣言文字列と割り当て文字列の違い , アクセス数 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つの大きなバグを。

  1. を割り当てている。 char の値を pointer-to-char という変数があります。コンパイラはこのことについて警告しているはずです。( char *p3 = *p1 ).
  2. お使いのコンパイラによっては、ポインタ %p フォーマット指定子ではなく、アドレスを出力するための %d (整数)形式指定子。
  3. あなたが使っているのは、文字列 %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