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'
}