Инициализатор литеральной строки для массива символов - PullRequest
34 голосов
/ 10 января 2010

В следующих правилах для случая, когда массив распадается на указатель:

Значение l [см. Вопрос 2.5] типа array-of-T, которое появляется в выражении, распадается (с тремя исключениями) на указатель на его первый элемент; тип результирующего указателя - указатель на T.

(Исключение составляют случаи, когда массив является операндом оператора sizeof или & или является инициализатором литеральной строки для массива символов.)

Как понять случай, когда массив является «инициализатором литеральной строки для массива символов»? Некоторые примеры, пожалуйста.

Спасибо!

Ответы [ 4 ]

46 голосов
/ 10 января 2010

Три исключения, когда массив не распадается на указатель, следующие:

Исключение 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) */
}
8 голосов
/ 12 января 2010

Предположим, декларации

char foo[] = "This is a test";
char *bar  = "This is a test";

В обоих случаях тип строкового литерала "This is a test" равен "15-элементный массив символов char". В большинстве случаев выражения массива неявно преобразуются из типа «массив из N элементов из T» в «указатель на T», и выражение вычисляется по адресу первого элемента массива. В объявлении для bar именно так и происходит.

В объявлении для foo, однако, выражение используется для инициализации содержимого другого массива и поэтому не преобразуется в тип указателя; вместо этого содержимое строкового литерала копируется в foo.

5 голосов
/ 10 января 2010

Это инициализатор литеральной строки для массива символов:

char arr[] = "literal string initializer";

Также может быть:

char* str = "literal string initializer";

Определение из K & R2:

Строковый литерал, также называемый строкой константа, это последовательность символов в двойных кавычках, как в "...". Строка имеет тип `` массив символы и класс хранения статические (см. пункт A.3 ниже) и инициализируется с заданными символами. Будь то идентичные строковые литералы различны определяется реализацией, а поведение программы, которая пытается изменить строковый литерал не определено.

2 голосов
/ 10 января 2010

Похоже, вы извлекли эту цитату из часто задаваемых вопросов о comp.lang.c (возможно, старой или печатной версии; она не совсем соответствует текущему состоянию онлайн):

http://c -faq.com / aryptr / aryptrequiv.html

Соответствующий раздел содержит ссылки на другие разделы часто задаваемых вопросов для уточнения этих исключений. В вашем случае вы должны посмотреть на:

http://c -faq.com / Децл / strlitinit.html

...