配列がポインターに減衰する場合の次の規則:
式に現れる array-of-T 型の左辺値 [質問 2.5 を参照] は、(3 つの例外を除いて) その最初の要素へのポインターに崩壊します。結果のポインターの型は T へのポインターです。
(例外は、配列が sizeof または & 演算子のオペランドであるか、文字配列のリテラル文字列初期化子である場合です。)
配列が「文字配列のリテラル文字列初期化子」の場合を理解する方法は? いくつかの例をお願いします。
ありがとう!
配列がポインターに変化しない 3 つの例外は、次のとおりです。
例外 1. — 配列が のオペランドである場合sizeof
。
int main()
{
int a[10];
printf("%zu", sizeof(a)); /* prints 10 * sizeof(int) */
int* p = a;
printf("%zu", sizeof(p)); /* prints sizeof(int*) */
}
例外 2. — 配列が&
演算子のオペランドである場合。
int main()
{
int a[10];
printf("%p", (void*)(&a)); /* prints the array's address */
int* p = a;
printf("%p", (void*)(&p)); /*prints the pointer's address */
}
例外 3. — 配列がリテラル文字列で初期化される場合。
int main()
{
char a[] = "Hello world"; /* the literal string is copied into a local array which is destroyed after that array goes out of scope */
char* p = "Hello world"; /* the literal string is copied in the read-only section of memory (any attempt to modify it is an undefined behavior) */
}
宣言を仮定する
char foo[] = "This is a test";
char *bar = "This is a test";
どちらの場合も、文字列リテラル " This is a test
" の型は "char の 15 要素配列" です。ほとんどの場合、配列式は "T の N 要素配列" 型から "T へのポインター" 型に暗黙的に変換され、式は配列の最初の要素のアドレスに評価されます。の宣言ではbar
、まさにそれが起こります。
ただし、の宣言でfoo
は、式は別の配列の内容を初期化するために使用されているため、ポインター型に変換されません。代わりに、文字列リテラルの内容が にコピーされfoo
ます。
これは、文字配列のリテラル文字列初期化子です。
char arr[] = "literal string initializer";
次の場合もあります。
char* str = "literal string initializer";
K&R2 からの定義:
文字列定数とも呼ばれる文字列リテラルは、"..." のように二重引用符で囲まれた一連の文字です。文字列は ``文字配列'' 型であり、ストレージ クラスは static (以下の Par.A.3 を参照) であり、指定された文字で初期化されます。同一の文字列リテラルが異なるかどうかは実装によって定義され、文字列リテラルを変更しようとするプログラムの動作は未定義です。
その引用は comp.lang.c FAQ から引用したようです (古いバージョンか、印刷されたバージョンの可能性があります。オンラインのものの現在の状態とは完全には一致しません)。
http://c-faq.com/aryptr/aryptrequiv.html
対応するセクションは、FAQ の他のセクションにリンクしており、これらの例外について詳しく説明しています。あなたの場合、次を確認する必要があります。