Ли строковый литерал считается частичным инициализатором и нулевой инициализацией?

В C вы можете частично инициализировать структуру или массив, в результате чего элементы/элементы, которые не упоминаются в инициализаторе, инициализируются нулем. (Раздел C99 6.7.8.19). Например: -

int a[4] = {1, 2};
// a[0] == 1
// a[1] == 2
// a[2] == 0
// a[3] == 0

Вы также можете инициализировать "массив типа символа" строковым литералом (раздел C99 6.7.8.14), а "последовательные символы... инициализировать элементы массива". Например: -

char b[4] = "abc";
// b[0] == 'a'
// b[1] == 'b'
// b[2] == 'c'
// b[3] == '\0'

Все довольно просто. Но что произойдет, если вы явно указали длину массива, но используете литерал, слишком короткий для заполнения массива? Остальные символы ноль-инициализированы или имеют значения undefined?

char c[4] = "a";
// c[0] == 'a'
// c[1] == '\0'
// c[2] == ?
// c[3] == ?

Рассмотрение его как частичного инициализатора имело бы смысл, оно делало бы char c[4] = "a" вести себя точно так же, как char c[4] = {'a'}, и это имело бы полезный побочный эффект, позволяя вам с нулевой инициализацией массива всего символа с помощью char d[N] = "", но это совсем не ясно для меня, что то, что требует спецификация.

Ответ 1

 char c[4] = "a";

Все остальные элементы массива будут установлены в 0. То есть не только c[1], но также c[2] и c[3].

Обратите внимание, что это не зависит от продолжительности хранения c, i. е. даже если c имеет автоматическую продолжительность хранения, остальные элементы будут установлены на 0.

Из стандарта C (ударный удар):

(C99, 6.7.8p21) "Если в списке, заключенном в фигурные скобки, меньше инициализаторов, чем в элементе или элементах совокупности, или меньше символов в строковом литерале используется для инициализации массив с известным размером, чем есть элементы в массиве, оставшаяся часть агрегата должна быть инициализирована неявно так же, как объекты со статической продолжительностью хранения."

Ответ 2

Из стандарта C99 (как уже указано ouah):

Если в списке, заключенном в фигурные скобки, меньше инициализаторов, чем элементов или элементов совокупности или меньше символов в строковом литерале, используемом для инициализации массива известных размера, чем есть элементы в массиве, остальная часть совокупности должна быть инициализируется неявно так же, как и объекты, имеющие статическую продолжительность хранения.

и

Если объект с автоматической продолжительностью хранения не инициализируется явно, его значение неопределенно. Если объект с длительностью статического хранения не инициализируется явно, то:

  • если он имеет тип указателя, он инициализируется нулевым указателем;
  • если он имеет арифметический тип, он инициализируется нулем (положительным или без знака);
  • если он является агрегатом, каждый член инициализируется (рекурсивно) в соответствии с этими правилами;
  • если это объединение, первый именованный элемент инициализируется (рекурсивно) в соответствии с этими правила.

И char - это арифметический тип, поэтому оставшиеся элементы массива будут инициализированы до нуля.

Ответ 3

Абсолютно всюду на языке C он следует принципу "все или ничего" для инициализации. Если вы инициализируете агрегат только частично, остальная часть этого агрегата получает нуль-инициализацию.

Можно сказать, что это чрезмерное и менее оптимальное с помощью строк, но это то, как он работает на C.