C char инициализация массива
Я не уверен, что будет в массиве char после инициализации следующими способами.
1. char buf[10] = "";
2. char buf[10] = " ";
3. char buf[10] = "a";
Для случая 2, я думаю, buf[0]
должен быть ' '
, buf[1]
должен быть '\0'
, а от buf[2]
до buf[9]
будет случайным. Для случая 3 я думаю, что buf[0]
должен быть 'a'
, buf[1]
должен быть '\ 0', а от buf[2]
до buf[9]
будет случайным.
Правильно ли это?
А для случая 1, что будет в buf
? buf[0] == '\0'
и от buf[1]
до buf[9]
будет случайным содержимым?
Ответы
Ответ 1
Это не то, как вы инициализируете массив, но для:
-
Первая декларация:
char buf[10] = "";
эквивалентно
char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
Второе объявление:
char buf[10] = " ";
эквивалентно
char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
Третья декларация:
char buf[10] = "a";
эквивалентно
char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
Как вы можете видеть, никакого случайного контента: если инициализаторов меньше, оставшийся массив инициализируется с помощью 0
. Этот случай, даже если массив объявлен внутри функции.
Ответ 2
Edit: OP (или редактор) молча изменил некоторые одиночные кавычки в исходном вопросе на двойные кавычки в какой-то момент после предоставления этого ответа.
В результате ваш код приведет к ошибкам компилятора. Ваш первый фрагмент кода:
char buf[10] ; buf = ''
является дважды незаконным. Во-первых, в C нет такой вещи, как пустой char
. Вы можете использовать двойные кавычки для обозначения пустой строки, например:
char* buf = "";
Это даст вам указатель на строку NUL
, т.е. односимвольную строку, содержащую только символ NUL
. Но вы не можете использовать одинарные кавычки без ничего внутри них - это undefined. Если вам нужно назначить символ NUL
, вы должны указать его:
char buf = '\0';
Обратная символьная косая черта необходима для устранения неоднозначности символа '0'
.
char buf = 0;
выполняет одно и то же, но первое, по-моему, немного менее двусмысленное для чтения.
Во-вторых, вы не можете инициализировать массивы после их определения.
char buf[10];
объявляет и определяет массив. Идентификатор массива buf
теперь является адресом в памяти, и вы не можете изменить, где buf
указывает на назначение. Итак,
buf = // anything on RHS
является незаконным. По этой причине ваши второй и третий фрагменты кода являются незаконными.
Чтобы инициализировать массив, вы должны сделать это во время определения:
char buf [10] = ' ';
предоставит вам 10-значный массив с первым char, являющимся пространством '\040'
, а остальное будет NUL
, т.е. '\0'
. Когда массив объявляется и определяется с помощью инициализатора, элементы массива (если они есть) мимо тех, у которых заданные начальные значения, автоматически дополняются с помощью 0
. Не будет никакого "случайного контента".
Если вы объявляете и определяете массив, но не инициализируете его, как в следующем:
char buf [10];
у вас будет случайный контент во всех элементах.
Ответ 3
-
Это эквивалент
char buf[10] = "";
char buf[10] = {0};
char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
Это эквивалент
char buf[10] = " ";
char buf[10] = {' '};
char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
Это эквивалент
char buf[10] = "a";
char buf[10] = {'a'};
char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
Ответ 4
Соответствующая часть инициализации стандартного проекта C11 standard n1570 6.7.9 гласит:
14 Массив типа символа может быть инициализирован литералом строки символов или строкой UTF-8 буквальный, необязательно заключенный в фигурные скобки. Последовательные байты строкового литерала (включая завершение нулевого символа, если есть место или массив неизвестного размера) инициализировать элементов массива.
и
21 Если в списке с фигурной скобкой есть меньше инициализаторов, чем есть элементы или члены совокупности или меньше символов в строковом литерале, используемом для инициализации массива известных размера, чем есть элементы в массиве, остальная часть совокупности должна быть инициализируется неявно тем же, что и объекты, имеющие статическую продолжительность хранения.
Таким образом, добавляется '\ 0', , если достаточно места, а остальные символы инициализируются значением, которое будет инициализировано static char c;
внутри функции.
Наконец,
10 Если объект с автоматической продолжительностью хранения не инициализирован явно, его значение равно неопределенный. Если объект с статическим или длительностью хранения потоков не инициализирован явно, тогда:
[-]
- если он имеет арифметический тип, он инициализируется нулем (положительным или без знака);
[-]
Таким образом, char
является арифметическим типом, оставшаяся часть массива также может быть инициализирована нулями.
Ответ 5
Интересно, что в любой момент в программе можно инициализировать массивы, если они являются членами struct
или union
.
Пример программы:
#include <stdio.h>
struct ccont
{
char array[32];
};
struct icont
{
int array[32];
};
int main()
{
int cnt;
char carray[32] = { 'A', 66, 6*11+1 }; // 'A', 'B', 'C', '\0', '\0', ...
int iarray[32] = { 67, 42, 25 };
struct ccont cc = { 0 };
struct icont ic = { 0 };
/* these don't work
carray = { [0]=1 }; // expected expression before '{' token
carray = { [0 ... 31]=1 }; // (likewise)
carray = (char[32]){ [0]=3 }; // incompatible types when assigning to type 'char[32]' from type 'char *'
iarray = (int[32]){ 1 }; // (likewise, but s/char/int/g)
*/
// but these perfectly work...
cc = (struct ccont){ .array='a' }; // 'a', '\0', '\0', '\0', ...
// the following is a gcc extension,
cc = (struct ccont){ .array={ [0 ... 2]='a' } }; // 'a', 'a', 'a', '\0', '\0', ...
ic = (struct icont){ .array={ 42,67 } }; // 42, 67, 0, 0, 0, ...
// index ranges can overlap, the latter override the former
// (no compiler warning with -Wall -Wextra)
ic = (struct icont){ .array={ [0 ... 1]=42, [1 ... 2]=67 } }; // 42, 67, 67, 0, 0, ...
for (cnt=0; cnt<5; cnt++)
printf("%2d %c %2d %c\n",iarray[cnt], carray[cnt],ic.array[cnt],cc.array[cnt]);
return 0;
}
Ответ 6
Я не уверен, но я обычно инициализирую массив для ""
в этом случае мне не нужно беспокоиться о нулевом конце строки.
main() {
void something(char[]);
char s[100] = "";
something(s);
printf("%s", s);
}
void something(char s[]) {
// ... do something, pass the output to s
// no need to add s[i] = '\0'; because all unused slot is already set to '\0'
}