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

#include <stdio.h>
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", он этого не сделает.

Кто-нибудь, пожалуйста, объясните, почему это так?

c
2
azurepancake 1 Янв 2016 в 21:23

4 ответа

Лучший ответ

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

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

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

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

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

5
cadaniluk 1 Янв 2016 в 18:29

newyear должен заканчиваться '\0' вместо newline, чтобы быть строкой C. Затем вы можете поместить newline в оператор 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);

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

0
Weather Vane 1 Янв 2016 в 18:40

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

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

0
Jack 1 Янв 2016 в 18:26

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

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

0
Some programmer dude 1 Янв 2016 в 18:25