Инициализация 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