Подтвердить что ты не робот

Скобки вокруг строкового литерала в объявлении массива 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.

4b9b3361

Ответ 1

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

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

Это означает, что оба

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 }

Ответ 2

Скобки необязательны, и выражение эквивалентно только массиву 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.

Ответ 3

Любая переменная в (int, char и т.д.) является всего лишь массивом длины 1.

char s = {0};

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

Ответ 4

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

Ответ 5

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

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

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

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

Ответ 6

Это разрешено также стандартом С++, Citation:

[dcl.init.string] §1

Массив узкосимвольного типа ([basic.fundamental]), char16_t array, char32_t array или wchar_t array может быть инициализирован узким строковым литералом, char16_t строковым литералом, строковым литералом char32_t или широким строковым литералом, соответственно, или с помощью строго заданного строкового литерала , заключенного в фигурные скобки ([lex.string]). [Надрез]