2015-11-10 2 views
0
#include<stdio.h> 
int main() 
{ 
    char a[4] = {'7','4','5'}; 
    for(int i=0; a[i] != '\0'; i++) 
    printf("%c\n", a[i]); 
} 

Поскольку компилятор автоматически обнуляет массив, упомянутый код работает должным образом.Неоднозначность при явной инициализации массивов в C

Но когда я меняю строку 4 на char a[] = {'7', '4', '5'};, код по-прежнему работает, но отпечатывает несколько дополнительных символов за пределами строки.

Мой вопрос в том, почему компилятор не завершает работу массива с нулевым значением во втором случае.

+0

Зачем компилятору автоматически nul-terminate массив? Это не правда. Это верно, только если вы инициализируетесь строковым литералом. –

+1

В первом случае, как вы говорите, ''/0''-терминатор предоставляется компилятором, чтобы заполнить размер массива до 4. Но во втором случае длина массива равна только 3, поэтому не было установлено терминатор. Вам нужно будет определить 'char a [] =" 745 ";' для получения терминатора. –

ответ

4

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

char a[14] = {'7', '4', '5'}; // Compiler provides 11 zeros 

или вообще, если указать N инициализаторами для массива N элементов нет элементов:

char a[3] = {'7', '4', '5'}; // Compiler provides no zeros 

Когда вы позволяете компилятору вывести размер массива из инициализаторов, нет элементов, оставшихся нулевым инициализированным, потому что массив имеет ровно три элемента: '7', '4' и '5'. Нет места для '\0', потому что это эквивалентно ситуации выше, когда компилятор не предоставляет никаких дополнительных нулей.

Вот почему, если вы хотите нулевое завершение вам нужно сделать это самостоятельно, как этот

char a[] = {'7', '4', '5', '\0'}; 

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

char a[] = "745"; 

Примечание: компилятор обеспечит нулевой терминатор для char массивов инициализируются с строковых литералов только тогда, когда имеется достаточное пространство для терминатора в массиве. Например, char a[3] = "745" не будет завершен, потому что нет места для '\0'.

+1

Просто добавьте, что компилятор не добавит '' \ 0'', если строка lteral имеет точно такой размер массива: 'char a [3] =" 745 ";'. Поэтому для массива с заданной длиной он не отличается, если вы предоставляете строковый литерал или нет. – Olaf

+0

@ Олаф Не так ли? Или он просто переполнит массив? –

+0

@ Olaf Edited. Благодаря! – dasblinkenlight

0

Вы объявили первый массив как 4-элементный массив char и только явно инициализировали первые три элемента. В результате компилятор неявно инициализировал четвертый элемент равным 0 (компилятор не обрабатывает массив как строку , хотя это просто правило, что, если число инициализаторов не так много, как есть элементы в массиве , остальные элементы инициализируются до 0 или NULL в зависимости от типа массива).

Вы объявили второй массив в качестве 3-элемента массива char в явном виде и инициализируется все элементов (размер массива берутся из числа инициализаторов). Там нет места для нулевого терминатора, и компилятор не расширяет массив, чтобы вставить его.

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