Инициализация char Массив с меньшим строковым литералом

Если я пишу:

char arr[8] = "abc";

Есть ли какая-либо спецификация, над которой может быть arr[4]? Я провел несколько тестов с Clang, и кажется, что остальные символы в массиве имеют значение null. Кроме того, char arr[8] = ""; обнуляет каждый байт. Не уверен, что это компилятор удобство, стандартное поведение, чистое совпадение или я ошибался.


void a()
{
    char arr[8] = "abc";    /* breakpoint here, line 3 */
    strcpy(arr, "1234567");
}
int main()
{
    a();
    a();
    return 0;
}

Расшифровка отладки:

Breakpoint 1, a () at str.c:3
3           char arr[8] = "abc";
(gdb) s
Current language:  auto; currently minimal
4           strcpy(arr, "1234567");
(gdb) p arr
$1 = "abc\000\000\000\000"
(gdb) c      
Continuing.

Breakpoint 1, a () at str.c:3
3           char arr[8] = "abc";
(gdb) p arr
$2 = "1234567"
(gdb) s
4           strcpy(arr, "1234567");
(gdb) p arr
$3 = "abc\000\000\000\000"

Ответ 1

Это стандартное поведение.

arr[3] инициализируется на 0, поскольку завершение 0 является частью строкового литерала.

Все остальные элементы также инициализируются до 0 - ISO/IEC 9899: 1999, 6.7.8, 21:

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

И char объекты со статическим хранилищем инициализируются до 0.

Ответ 2

char arr[8] = "abc";

полностью эквивалентна

char arr[8] = {'a', 'b', 'c', '\0'};

ISO C 6.7.8 §21 утверждает, что

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

В простом английском языке это означает, что все значения в конце вашего массива будут установлены равными 0. Таким образом, стандарт гарантирует, что ваш код эквивалентен:

char arr[8] = {'a', 'b', 'c', '\0', 0, 0, 0, 0};

Теперь, конечно, '\ 0' также является нулевым значением.

Это правило универсально для всех массивов, а не только для строк. Кроме того, то же самое применяется при инициализации структуры, но только в явной установке нескольких ее членов (6.7.8 §18).


Вот почему вы можете написать код типа

char arr[8] = "";

В этом примере первый элемент массива инициализируется экспликацией в '\ 0', а остальные элементы неявно равны нулю. Компилятор переводит это на

char arr[8] = {0, 0, 0, 0, 0, 0, 0, 0};

Ответ 3

Это стандартное поведение. Каждый элемент массива, который явно не инициализирован, инициализируется значением по умолчанию ('\0' для char), если в объявлении инициализируется какой-либо префикс массива. Он также работает для других типов:

int a[10] = {1};

обнуляет a[1] через a[9].

Ответ 4

В соответствии со стандартом все индексы, превышающие заданные, будут установлены равными нулю /null. Дополнительная информация в этом сообщении SO