2015-05-18 2 views
3

Может кто-нибудь объяснить мне, почему int array[3] = {1,2,3} работает, но char array[3] = "123" не работает?Объявление статического символа массива в C

Он распечатал «123 ((» вместо «123».

Следует сказать, что для массив символов нужно другое место для нулевого символа, но запустился не массив от 0 так char array[3] достаточно, так как есть на самом деле 4 Если для массива символов фактически требуется 2 пробела для нуль и один для специального символа.

ответ

3

При объявлении массива в c, char array [3] даст 3 символа, а не 4, как вы предложили в своем вопросе. необходимо пространство для нулевого символа в конце строки, поэтому в этом случае вам понадобится массив символов [4].

6
int array[3] = {1,2,3} 

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

array[0] 
array[1] 
array[2] 

Здесь:

char array[3] = "123" 

"123" состоит из 4 байт. Символы в строковом литерале заканчиваются NUL-терминатором. Но вы выделяете 3 байта и можете удерживать 2 символа (+1 для NUL-терминатора). Итак, когда вы инициализируете массив с ним, '\0' не записывается, так как нет места.

При печати с использованием этого %s в printf, он не вызывает Undefined behavior как %s печатает все, пока NUL-терминатор. Таким образом, printf продолжает считывать значения из недопустимых мест памяти до '\0'. Все может случиться, когда вы это сделаете. Вы можете увидеть случайный вывод мусора, сбои, ошибки сегментации и т. Д. В принципе, вы никогда не должны полагаться на это поведение, даже если оно, казалось, «работало», как ожидалось.

но не массив начинается с 0

Да

так char array[3] достаточно, так как он на самом деле 4 пространство

Неправильно. Допустимые показатели для char array[3] являются

array[0] 
array[1] 
array[2] 

доступа array[3] неправильно и это вызывает Undefined Behavior.


Исправлена ​​проблема с использованием

char array[4] = "123"; 

или лучше:

char array[] = "123"; 

Пустые скобки говорят компилятору, чтобы определить размер массива.

+1

Доступ к 'array [3]' конечно это неопределенное поведение, но инициализация 'array' сама определена так, что инициализация' array' выше эквивалентна 'char array [] = {'1', '2', '3'}; '. Номер для нулевого терминатора не является обязательным. С другой стороны, 'char array [3] =" 1234 ";' undefined, поскольку "ни один инициализатор не пытается указать значение для объекта, не содержащегося в инициализированном объекте" (C11 draft N1570 6.7.9p2), что означает что 'array' слишком мал, чтобы содержать 4 элемента' {'1', '2', '3', '4'} '. 6.7.9p32 из N1570 выражает предполагаемое поведение. –

+0

@ ChronoKitsune, я этого не знал! Итак, '' \ 0'' не поставляется? –

+1

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