Неопределенное поведение (?) В C с массивами символов - PullRequest
0 голосов
/ 06 июля 2010

когда я пытаюсь

    char bla[32] = "foobar";
    int i;
    putchar(bla[i]);

с strlen(bla) < i < 32, bla[i] всегда \0.но разве это не неопределенное поведение, и его следует избегать?

Ответы [ 7 ]

5 голосов
/ 06 июля 2010

В разделе 6.7.8 стандарта C99 в пункте 21 говорится:

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

А в параграфе 10 говорится, что статические арифметические типы (которые будут включать символ) инициализируются нулями.

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

4 голосов
/ 06 июля 2010

Спецификация C89, раздел 8.7 «Инициализация»:

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

Таким образом, в вашем использовании завершающие символы инициализируются нулями.

2 голосов
/ 06 июля 2010
Язык

C следует принципу "все или ничего" , когда дело доходит до инициализации.Объект либо полностью неинициализирован, либо полностью инициализирован.Последнее означает, что если вы указываете меньше инициализаторов, чем необходимо для инициализации всего объекта, остальная часть объекта неявно инициализируется нулем для вас компилятором.

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

int a[100] = { 1 };

вы получите массив 100 int с, самый первый из которых инициализирован с 1, а остальные установлены на 0.

1 голос
/ 06 июля 2010

Я думаю, что это хорошо определенное поведение, на самом деле особенность.Пока вы инициализируете один элемент в массиве или struct, все остальные элементы, которые не были явно инициализированы, инициализируются в 0.

0 голосов
/ 06 июля 2010

Это не «функция» компилятора, а хорошо документированное поведение. Язык программирования C не гарантирует значение неинициализированной переменной. Поэтому вы просто догадываетесь, что я ценю, и вы можете легко получить доступ к памяти, которая не принадлежит вашему процессу и, например, на платформе Windows, это приведет к исключению нарушения прав доступа. См. http://en.wikipedia.org/wiki/Uninitialized_variable для получения дополнительной информации.

0 голосов
/ 06 июля 2010

Тот факт, что это неопределенное поведение, означает, что он может делать все что угодно. Он может делать то же самое каждый раз, но то, что сделано, остается только догадываться.

0 голосов
/ 06 июля 2010

Содержимое неинициализированной части массива зависит от того, где он находится (т.е. на каком сегменте данных). Если он находится в стеке, неинициализированные элементы являются случайными значениями. Обычно, если это массив global-scope, начальное содержимое также не определено. Если он снабжен спецификатором static, компилятор инициализирует его содержимое нулями при запуске программы.

Доступ к этой неинициализированной части не запрещен, и это не предполагает неопределенного поведения, но результат может быть неопределенным. Даже доступ к bla[i], если i > sizeof(bla) не является неопределенным поведением, так как у вас будет случайное значение или исключение ошибки сегментации.

...