Когда printf ("% s", char *) останавливает печать? - PullRequest
13 голосов
/ 28 апреля 2010

В моем классе мы пишем нашу собственную копию функции 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 *) перестает печатать символы?

Ответы [ 4 ]

28 голосов
/ 28 апреля 2010

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

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

5 голосов
/ 28 апреля 2010

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

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

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

3 голосов
/ 28 апреля 2010

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

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

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

0 голосов
/ 28 апреля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...