Я изучаю C и в настоящее время экспериментирую с хранением строк в переменных. Я собрал следующее, чтобы попробовать разные вещи.

#include 
int main() {
    char *name = "Tristan";
    char today[] = "January 1st, 2016";
    char newyear[] = {'H','a','p','p','y',' ','N','e','w',' ','Y','e','a','r','!','\n'};
    printf("Hello world!\n");
    printf("My name is %s.\n", name);
    printf("Today is: %s.\n", today);
    printf(newyear);
    return 0;
}

После компиляции этого кода и его запуска я получаю следующие результаты:

Hello world!
My name is Tristan.
Today is: January 1st, 2016.
Happy New Year!
January 1st, 2016

Это примерно то, что я ожидал, почему «1 января 2016» снова распечатывается в конце вывода программы?

Если я возьму "\ n" из массива "newyear", он этого не сделает.

Не могли бы вы объяснить, почему это так?

azurepancake

Ответов: 4

Ответы (4)

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

Неопределенное поведение означает, что произойдет то, что стандарт не определяет в этом случае. Это включает в себя, что ничего не происходит, вы плачете или, да, печатаете какую-то строку дважды.

Просто добавьте в массив дополнительный символ, т.е. нулевой байт, чтобы решить проблему:

char newyear[] = {'H','a','p','p','y',' ','N','e','w',' ','Y','e','a','r','!','\n', '\0'};

Обратите внимание, что ни один здравомыслящий человек не инициализирует автоматический массив char такой строкой. Просто придерживайтесь строковых литералов! (Я думаю, что вы сделали это просто в учебных целях.)

новый год должен заканчиваться '\ 0' вместо новой строки, чтобы быть строкой C. Затем вы можете поместить новую строку в оператор printf, как и другие:

char newyear[] = {'H','a','p','p','y',' ','N','e','w',' ','Y','e','a','r','!','\0'};
//...
printf("%s.\n", newyear);

Или вы можете добавить терминатор строки в массив и использовать printf, как вы это делали:

char newyear[] = {'H','a','p','p','y',' ','N','e','w',' ','Y','e','a','r','!','\n','\0'};
//...
printf(newyear);

В ваших первых двух примерах к строке, определенной как «моя строка», компилятор автоматически добавляет '\ 0'.

Это потому, что вы определяете newyear непосредственно как массив char, а не через синтаксис строкового литерала "". Это предотвращает добавление компилятором завершающего символа \ 0, который требуется для обозначения конца строки.

Поскольку оба newyear и сегодня находятся в стеке, в этом случае они имеют непрерывное хранилище, поэтому printf сохраняется после \ n of newyear и печатает содержимое памяти, пока не будет найдено \ 0.

Помните, что строки в C заканчиваются специальным символом '\ 0'.

Отсутствие этого терминатора в конце данных, которые обрабатываются как строка, приведет к неопределенному поведению, поскольку строковые функции передают конец данных, ищущих терминатор.

2022 WebDevInsider