Другие авторы уже объяснили вам, что в вашем примере
char bar[3] = "bar";
терминатор строки не помещается в массив, поэтому строка заканчивается без конца.Формально говоря, это даже не строка (так как строки должны заканчиваться по определению).Вы пытаетесь напечатать не строку как строку (используя спецификатор формата %s
), что приводит к неопределенному поведению.Неопределенное поведение - это именно то, что вы наблюдаете.
В языке C ++ (например) объявление
char bar[3] = "bar";
было бы недопустимым, поскольку C ++ не позволяет "падать" нулевому терминатору вдекларация, как это.C позволяет это, но только для неявного символа нулевого терминатора.Объявление
char bar[3] = "barr";
недопустимо как в C, так и в C ++.
Опять же, трюк с отсутствующим нулем работает в C только с неявным нулевым символом-ограничителем.Он не работает ни с одним явным инициализатором: вам не разрешено явно указывать больше инициализаторов, чем имеется элементов в массиве.Что подводит нас к вашему третьему примеру.В третьем примере у вас есть объявление
char FOO[3] = { 'F', 'O', 'O', '\0' };
, которое явно указывает 4 инициализатора для массива размера 3. Это недопустимо в C. Ваш третий пример не компилируется.Если ваш компилятор принял его без диагностического сообщения, ваш компилятор должен быть поврежден.Поведение вашей третьей программы не может быть объяснено языком Си, поскольку это не программа Си.