Строковый литерал, такой как "hello"
, хранится в статической памяти в виде массива char
с.Фактически строковый литерал имеет тип char [N]
, где N
- количество символов в массиве (включая терминатор \0
).В большинстве случаев идентификатор массива затухает до указателя на первый элемент массива, поэтому в большинстве выражений строковый литерал, такой как "hello"
, затухает до указателя на char
элемент 'h'
.
char *names[] = { "hello", "Jordan" };
Здесь два строковых литерала затухают до указателей на char
, которые указывают на 'h'
и 'J'
соответственно.То есть здесь строковые литералы имеют тип char *
после преобразования.Эти типы согласуются с объявлением слева, и массив names[]
(который является не массивом символьного типа, а массивом char *
) инициализируется с использованием этих двух значений указателя.
char names[] = "hello";
или аналогично:
char names[] = { "hello" };
Здесь мы сталкиваемся с особым случаем.Идентификаторы массива не преобразуются в указатели на их первые элементы, когда они являются операндами оператора sizeof
или унарного оператора &
, или когда они являются строковыми литералами, используемыми для инициализации массиватип символа .Так что в этом случае строковый литерал "hello"
не затухает до указателя;вместо этого символы, содержащиеся в строковом литерале, используются для инициализации массива names[]
.
char names[] = {"hello", "Jordan"};
Опять же, строковые литералы будут использоваться для инициализации массива names[]
, но есть избытокинициализаторы в списке инициализаторов.Это нарушение ограничения в соответствии со Стандартом.Из § 6.7.9 *2 проекта стандарта C11:
Ни один инициализатор не должен пытаться предоставить значение для объекта, не содержащегося в инициализируемой сущности.
Соответствующая реализация должна выдать диагностику в случае нарушения ограничения, которая может принимать форму предупреждения или ошибки.На версии gcc, которую я сейчас использую (gcc 6.3.0), эта диагностика является ошибкой:
error: excess elements in char array initializer
Тем не менее, для массивов char
, которые инициализируются списком инициализаторов char
значения, а не строковые литералы, такая же диагностика является предупреждением, а не ошибкой.
Чтобы инициализировать массив char
, который не является массивом указателей, вам понадобится 2d массивchar
с здесь.Обратите внимание, что второе измерение является обязательным и должно быть достаточно большим, чтобы содержать наибольшую строку в списке инициализатора:
char names[][100] = { "hello", "Jordan" };
Здесь каждый строковый литерал используется для инициализации массива из 100 char
с.в большем 2d массиве char
с.Или, другими словами, names[][]
- это массив массивов 100 char
с, каждый из которых инициализируется строковым литералом из списка инициализаторов.