Вопрос по c++, c, string, arrays – Брекеты вокруг строкового литерала в объявлении массива char действительны? (например, char s [] = {«Hello World»})

50

Случайно обнаружил, что линия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;
}

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

Постскриптум Мой компилятор gcc-4.3.4.

Я отправил подобный вопрос несколько месяцев назад:stackoverflow.com/questions/8061346/… Antoine
вау .. 40купило .. Jack
работает с mingw32 L7ColWinters

Ваш Ответ

6   ответов
3

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

char s = {0};

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

2

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

1

[dcl.init.string] §1

An array of narrow character type ([basic.fundamental]), char16_t array, char32_t array, or wchar_t array can be initialized by a narrow string literal, char16_t string literal, char32_t string literal, or wide string literal, respectively, or by an appropriately-typed string literal enclosed in braces ([lex.string]). [snip]

22

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

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

 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.
1

char *s[] = {"Hello World"}; the compiler accepts it as well, as expected

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

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

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

64

14:

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

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

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

а также

char s[] = "Hello World";

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

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

В соответствующей заметке (тот же раздел, & # xA7; 11), C также разрешает скобки вокруг скалярных инициализаторов, таких как

int foo = { 42 };

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

(int){ 42 }
@ Дэвид Кауден: использование{} в контексте инициализации не имеет абсолютно никакого отношения к их использованию в синтаксисе составного оператора.
В общем, фигурные скобки просто группируют все содержащиеся в них утверждения в одно большее предложение. Вот почему вам не нужно{ } за одну строчкуif ветви (или время и т. д.). Компилятор просто ищетnext statement послеif и выполняет это условно. Итак, если вы хотите две характеристики, просто сделайте их похожими, окружив их фигурными скобками.
Почти идентичный текст в C ++ 2003, пункт 8.5.2.
Возможность использовать лишние скобки вокруг инициализаторов для скалярных объектов также поддерживает «универсальный инициализатор нуля». идиома в языке Си, где= { 0 } может быть использован для инициализации объекта виртуальноany Тип с нулями.
@DavidCowden: это неправильно.a = (x = 1, y = 2, z = 3); установитa в3не1.

Похожие вопросы