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

если я напишу:

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
 = "abc0000"
(gdb) c      
Continuing.

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

4 ответов


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

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

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

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

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


char arr[8] = "abc";

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

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

ISO C 6.7.8 §21 гласит, что

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

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

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

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

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


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

char arr[8] = "";

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

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

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

int a[10] = {1};

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


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