2010-04-28 6 views
12

В моем классе мы пишем нашу собственную копию функции malloc() C. Для того, чтобы проверить свой код (который может в настоящее время выделить пространство штраф) Я использую:Когда printf ("% s", char *) прекращает печать?

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 

Что заставляет меня задаться вопросом, когда же Е («% S», символ *) остановить печать символов?

ответ

26

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

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

3

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

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

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

+0

Dur, я должен использовать \ 0 для завершения строки? Dur Dur Dur – user327406

+0

Вам не нужно добавлять \ 0 самостоятельно. Когда вы создаете литеральную строку или получаете ее как ввод, C добавляет ее для вас. Вы действительно не видите \ 0. Эта строка «Hello \ n» имеет семь символов, если вы посмотрите на фактический код сборки. – Uri

0

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

5

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

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

Кроме того, по определению, SizeOf (Char) == 1 в C, так 6*sizeof(char) избыточна

+2

6 * sizeof (char) может быть избыточным, но это, на мой взгляд, хорошая практика по простым причинам (1), если char на некоторой новой архитектуре не равен 1 или (2) этот код портирован на wchar_t .. .. – Eric

+4

Это была бы не просто новая архитектура, это был бы новый язык. Если 'sizeof (char)! = 1', вы больше не программируете в C. http://stackoverflow.com/questions/2215445/are-there-machines-where-sizeofchar-1 –