char a[]="this is an array of characters"; // declaration type 1
char *b="this is an array of characters";// declaration type 2
ここでは、2 つの変数 と を宣言しa
、b
それらを初期化しています。"this is an array of characters"
文字列リテラルであり、C では char 型の配列を持ちます。a
char の型配列を持ちます。この特定のケースでは、配列はポインターに変換されず、a
配列で初期化され"this is an array of characters"
ます。b
char へのポインター型を持ち、配列はポインターに変換され、配列へのポインターでb
初期化されます"this is an array of characters"
。
printf("%s",*b); // gives a segmentation fault
printf("%s",b); // displays the string
式で*b
は、ポインターを逆参照するb
ため、 が指す文字b
、つまり:に評価されますT
。これはアドレスではない ("%s" が期待するもの) ため、未定義の動作が発生し、おそらくクラッシュします (ただし、組み込みシステムでこれを実行しようとしないでください。不思議な動作や破損したデータが発生する可能性があります。クラッシュよりも悪い)。2 番目のケースで%s
は、char へのポインタを期待して取得し、処理を続行できます。
char *d=malloc(sizeof(char)); // 1)
scanf("%s",d); // 2)
printf("%s",d);// 3)
C ではsizeof
、オブジェクト (= ストレージの領域) のサイズをバイト単位で返します。C では、char はバイトと同じであると定義されており、少なくとも 8 ビットを持ちますが、それ以上のビットを持つこともできます (ただし、いくつかの標準では、追加の制限があります。たとえば、POSIX では 8 ビット バイトが必要です。したがって、1バイトを割り当てています。を呼び出すとscanf()
、 が指すメモリd
に制限なく書き込み、目に見えるすべてのものを上書きします。scanf()
最大フィールド幅を許可するため、次のようになります。
- 少なくとも必要なもの + 1 終了 ASCII NUL に十分な、より多くのメモリを割り当てます。
- 停止
scanf()
するように指示します。たとえばscanf("%19s")
、最大 19 文字 (終了する ASCII NUL を数えて、それを格納するには 20 バイトが必要です)。
そして最後に(マークダウンが許せば):
char c=malloc(sizeof(char)); // 4)
scanf("%c",c); // 5)
printf("%c",c);// 6)
c
はポインターではないため、アドレスを格納すべきではない場所に格納しようとしています。ではscanf
、"%c"
指定されたフィールド幅 (デフォルトでは 1) に十分なスペースを持つオブジェクト (= ストレージの領域) を指す必要がある char へのポインターが必要です。はポインターではないためc
、上記は一部のプラットフォームでクラッシュする可能性があります (他のプラットフォームではさらに悪い結果を引き起こします)。