Инициализация массива char с меньшим строковым литералом - PullRequest
12 голосов
/ 23 ноября 2011

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

char arr[8] = "abc";

Есть ли какая-либо спецификация, которая может быть arr[4]? Я сделал несколько тестов с Clang и кажется, что оставшиеся символы в массиве установлены в нуль. Также 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"

Ответы [ 4 ]

16 голосов
/ 23 ноября 2011

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

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

Все остальные элементы также инициализируются равными 0 - ИСО / МЭК 9899: 1999 , 6.7.8, 21:

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

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

7 голосов
/ 23 ноября 2011
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 голосов
/ 23 ноября 2011

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

int a[10] = {1};

обнуляет a[1] до a[9].

0 голосов
/ 23 ноября 2011

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

...