2010-07-06 2 views
0

при попыткеНеопределенное поведение (?) В C с массивы символов

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

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

+0

Никогда не забывайте переменные inicilizar. Это сэкономит вам массу неприятностей. Попробуйте поместить начальное значение для переменной i. – lsalamon

ответ

4

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

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

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

+0

Последнее замечание неверно. Вам не нужно явно добавлять '\ 0', потому что это всегда неявная часть любого строкового литерала. Итак, когда вы инициализируете массив символов строковым литералом, этот '\ 0' также« копируется »в целевой массив (при условии, что там достаточно места). – AnT

+0

@ AndreyT- Хороший улов (фиксированный) – bta

0

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

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

+0

, так что это просто компилятор «feature»? – guest

+1

это не функция компилятора, но спецификация C –

+0

@ n-alexander: не могли бы вы привести абзац в cstd? Я сейчас смотрю в нем, но не могу найти его. – guest

0

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

0

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

1

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

5

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

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

И в пункте 10 указано, что статические арифметические типы (которые включают char) инициализируются равными нулю.

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

+0

отлично! большое спасибо! – guest

2

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

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

int a[100] = { 1 }; 

вы получите массив из 100 int с с самим первым инициализированы с 1 и остальным набором для 0.

Смежные вопросы