char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
4 に答える
amessage
タイプchar[16]
です。配列です。配列の要素には、文字列リテラルの16文字が含まれています。
pmessage
タイプchar*
です。ポインタです。これは、文字列リテラルの16文字を含む(変更不可能な)配列を指します。(文字列リテラルを指すためにを使用することは避けてくださいchar*
。そうすることは悪です。文字列リテラルを参照するときは、可能な限り常に使用する必要がありconst char*
ます。)
James McNellisの答えに加えて、amessage
1つあります。スタック上の16文字の配列で、たまたま「now is thetime」という文字列が含まれています(作成時にそこにコピーされるためamessage
)。内容を変更できます。
一方、pmessage
文字列リテラル(メモリの書き込み不可能な部分に格納される)とポインタの2つがあります。文字列リテラルの内容を変更することはできませんが、ポインタが指すものを変更して、別の文字列を指すようにすることはできます。また、文字列リテラルを他のポインタのターゲットとして使用できます。
(ある意味では、これは完全に真実ではありません。コンテンツが作成されたときにコンテンツがコピーされる場所であるため、文字列リテラルも含まれます。ただし、後でその文字列リテラルを使用して他amessage
のことを行うことはできません。)
GCCを使用している場合は、-Wwrite-stringsをオンにします。固定文字列のタイプはconstchar[length_of_string]であり、char *に変換すると、警告が発生します[constである必要があります]。
最初の割り当ては文字配列の割り当てですが、2番目の割り当てはポインタベースの割り当てです(結果の文字列は固定文字列として保持されます)
最初の割り当てはそのまま受け入れられますが、2番目の割り当てにはconst修飾子が必要です。
最初の割り当てでは、ポイントの変更は許容されます(たとえば、amessage [3] ='q')。2番目の割り当てでは、ポイントの変更は受け入れられません(文字列がconstであるため)-バスエラーが発生するはずです
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
Cでは、「=」の左側にあるものは「左辺値」と呼ばれます。タイプは「左辺値」によってのみ定義されます。したがって、「amessage」はchar配列です。'pmessage'はcharへのポインタです。
Cでは、配列型と'char *'アクセスの間で同等であるものとそうでないものに関連して、さらに進んでいます。
宣言されているように、「pmessage」は変更可能な「左辺値」です-「amessage」は変更可能ではありません。したがって、「pmessage」を実際には変更できないようにconstとして宣言することをお勧めします。
例えば
const char* const pmessage = "...";
メモリアクセスに関しては、「amessage」は直接アクセスになりますが、「pmessage」は逆参照を必要とします。
注:Cコンパイラーは、コンパイル時に文字列リテラルを介した「char*」の初期化のみを許可します。
例:
1. {
2. int j = 1;
3. int *k = &j;
4. int *i = 1;
5. }
4行目は意味がなく、違法です。
Peter VanLindenの「DeepCSecrets」を強くお勧めします。彼は、C配列とポインターに関する全章を持っています。