Когда printf(%s, char*) перестает печатать?

В моем классе мы пишем собственную копию функции malloc() языка Си. Чтобы протестировать мой код (который в настоящее время может выделять пространство в порядке), я использовал:

char* ptr = my_malloc(6*sizeof(char));
memcpy(ptr, "Hello\n", 6*sizeof(char));
printf("%s", ptr);

Вывод обычно будет таким:

Hello
Unprintable character

Некоторая отладка показала, что мой код не вызывает этого сам по себе, поскольку память ptr выглядит следующим образом:

[24 байта метаинформации][количество запрошенных байтов][заполнение]

Итак, я решил, что printf проникает в отступы, что является просто мусором. Итак, я провел тест: printf("%s", "test\nd"); и получил:

test
d

Что заставляет меня задаться вопросом, когда printf("%s", char*) перестанет печатать символы?


person user327406    schedule 28.04.2010    source источник


Ответы (4)


Он прекращает печать, когда достигает нулевого символа (\0), потому что %s ожидает, что строка будет оканчиваться нулем (т. е. он ожидает, что аргумент будет строкой C).

Строковый литерал "test\nd" завершается нулем (все строковые литералы завершаются нулем). Однако ваш массив символов ptr не является таковым, потому что вы копируете только шесть символов в буфер (Hello\n) и не копируете седьмой символ — завершающий нуль.

person James McNellis    schedule 28.04.2010

Джеймс прав в том, что printf останавливается, когда он достигает нулевого символа, а Ури прав в том, что вам нужно выделить 7-символьный буфер для хранения «hello\n».

Некоторую путаницу с терминаторами можно было бы уменьшить, если бы вы использовали обычную идиому C для копирования строки: strcpy(ptr, "Hello\n"), а не memcpy.

Кроме того, по определению sizeof(char) == 1 в C, поэтому 6*sizeof(char) является избыточным

person David Gelhar    schedule 28.04.2010
comment
6*sizeof(char) может быть избыточным, но, на мой взгляд, это хорошая практика по простым причинам (1) если char на какой-то новой архитектуре не = 1 или (2) этот код портирован на wchar_t... . - person Eric; 10.05.2011
comment
Это будет не просто новая архитектура, это будет новый язык. Если sizeof(char) != 1, вы больше не программируете на C. > stackoverflow.com/questions/2215445/ - person David Gelhar; 10.05.2011

Строки C заканчиваются нулем (в конце есть символ \0), поэтому C знает, когда прекратить печать или работу с буфером как со строкой. Вы несете ответственность за то, чтобы никогда не размещать строку в более длинном пространстве, чем то, что вы выделили.

Обратите внимание, что Hello\n — это не строка из шести символов, а строка из семи символов. Вы используете пять для приветствия, один для новой строки и один для нулевого терминатора.

Попытка поместить 7 символов в шестисимвольный буфер считается ошибкой, я не уверен, что это связано с проблемами, которые у вас есть в настоящее время, но похоже, что копирование 6 символов не скопирует нулевой терминатор. Так что я бы на самом деле ожидал, что ваш отпечаток выйдет за рамки приветствия и превратится в настоящий мусор.

person Uri    schedule 28.04.2010
comment
Дур, я должен использовать \0 для завершения строк? Дур Дур Дур - person user327406; 28.04.2010
comment
Вам не нужно добавлять \0 самостоятельно. Когда вы создаете литеральную строку или получаете ее в качестве входных данных, C добавляет ее за вас. На самом деле вы не видите \0. Эта строка Hello\n состоит из семи символов, если вы посмотрите на реальный ассемблерный код. - person Uri; 28.04.2010

когда он достигает нуля. вам нужно 7 символов.

person Sanjay Manohar    schedule 28.04.2010