Фигурные скобки вокруг строкового литерала в объявлении массива char действительны? (например, char s [] = {"Hello World"})

случайно я обнаружил, что строка char s[] = {"Hello World"}; правильно скомпилирован и, похоже, обрабатывается так же, как char s[] = "Hello World";. Не первый ({"Hello World"}) массив, содержащий один элемент, который является массивом char, поэтому объявление для s должно читать char *s[]? На самом деле, если я изменю его на char *s[] = {"Hello World"}; компилятор также принимает его, как и ожидалось.

поиск ответа, единственное место, которое я нашел, которое упомянуло это этот но нет со ссылкой на норматив.

Итак, мой вопрос, почему строку char s[] = {"Hello World"}; компилируется, хотя левая сторона типа array of char и правая сторона имеет тип array of array of char?

Ниже приведена рабочая программа:

#include<stdio.h>
int main() {
    char s[] = {"Hello World"};
    printf("%s", s); // Same output if line above is char s[] = "Hello World";
    return 0;
}

Спасибо за любые разъяснения.

P. S. мой компилятор-это GCC-4.3.4.

6 ответов


это разрешено, потому что стандарт говорит так: C99 раздел 6.7.8, §14:

массив символьного типа может быть инициализирован символьным строковым литералом, необязательно заключенный в скобки. Последовательные символы символьного строкового литерала (включая завершающий нулевой символ, если есть номер или если массив неизвестного размера) инициализировать элементы массива.

это означает, что оба!--6-->

char s[] = { "Hello World" };

и

char s[] = "Hello World";

- это не более чем синтаксический сахар для

char s[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0 };

на связанной заметке (тот же раздел, §11), C также позволяет фигурные скобки вокруг скалярных инициализаторов, таких как

int foo = { 42 };

что, кстати, хорошо вписывается в синтаксис составных литералов

(int){ 42 }

фигурные скобки являются необязательными, и выражение эквивалентно просто массив char.

вы также можете написать это:

 int a = {100}; //ok

демо:http://ideone.com/z0psd

в самом деле C++11 обобщает этот самый синтаксис, чтобы инициализировать не-массивы, а также массивы равномерно. Так C++11, вы можете иметь эти:

int a{}; //a is initialized to zero, and it is NOT an array

int b[]{1,2,3,4}; //b is an array of size 4 containing elements 1,2,3,4

int c[10]{}; //all 10 elements are initialized to zero

int *d{}; //pointer initialized to nullptr

std::vector<int> v{1,2,3,4,5}; //vector is initialized uniformly as well.

любая переменная в (int, char, etc.)- это просто массив длины 1.

char s = {0};

работает так же.


Я могу ошибаться, но я думаю, что это не массив массивов символов, а блок содержит массив символов. int a = {1}; может также работать.


[...] На самом деле, если я изменю его на char * s [] = {"Hello World"}; компилятор принимает его также, как ожидалось

компилятор принимает его, потому что на самом деле вы делаете массив 2D элементов неопределенного размера,где вы сохранили только один элемент,"Hello World" строку. Что-то вроде этого:--5-->

char* s[] = {"Hello world", "foo", "baa" ...};

вы не можете пропустить bracets в этом случае.


это разрешено стандартом C++, а также, цитата:

[dcl.в этом.string] §1

массив узкого символьного типа ([basic.основополагающим]), массив, символьные типы char16_t, char32_t массив, или массив тип wchar_t может быть инициализирован узкий строковый литерал, строковый литерал строковые типы char16_t, char32_t строковый литерал, или широкий строковый литерал, соответственно, или соответствующим образом набранным строковым литералом заключенный в скобки ([Лекс.строка.)] [snip]