2010-05-10 2 views
2

Как различные функции, которые берут строку формата printf, ведут себя при столкновении с форматом %c, заданным значением \0/NULL? Как они должны себя вести? Это безопасно? Определено ли это? Является ли он специфичным для компилятора?printf ("...% c ...", ' 0') и семья - что произойдет?

например. sprintf() - он обрезает строку результата в NULL? Какую длину он вернет?

Будет ли printf() выводить всю строку формата или только до нового значения NULL?

Will va_args + vsprintf/vprintf как-то повлияет? Если да, то как?

Я могу рискнуть утечками памяти или другими проблемами, если я, например. запустите этот NULL в точке в std :: string.c_str()?

Каков наиболее эффективные способы избежать этой оговорки (санировать вход?)

+2

Макрос NULL и символ '\ 0' - это не одно и то же. Последнее часто обозначается как NUL, имеющим ASCII, но это не то же самое, что и NULL. – Clifford

+0

@Clifford: Системы, в которых NULL не был нулем, существовали в прошлом, но в наши дни, если вы не программируете какие-то давно устаревшие большие динозавры, вы не рискуете столкнуться с этим предостережением. –

+0

Думаю, вы пропустили мою точку - 'NULL' - это макрос, представляющий указатель на нуль *, а' \ 0' - это символьная константа (типа 'int' в C и' char' в C++). Кроме того, независимо от фактического машинного зависимого битового шаблона нулевого указателя, C++ * гарантирует *, что нуль может быть неявно преобразован в такой указатель. Моя точка зрения заключалась в том, что в этом контексте вы можете ссылаться на nul, null-character, NUL или '\ 0', но не должны использовать макрос' NULL' для представления такого символа. Размещение слова в «разметке кода» может означать NULL-макрос. – Clifford

ответ

3

Что происходит, когда вы выводите NUL, зависит от устройства вывода.

Это непечатаемый символ, то есть isprint('\0') == 0; поэтому при выходе на дисплейное устройство он не оказывает заметного влияния. Однако при перенаправлении в файл (или при вызове fprintf()) он вставляет в файл NUL (нулевой байт); смысл этого будет зависеть от того, как используется файл.

При выводе на строку C он будет интерпретироваться как ограничитель строк стандартными функциями обработки строк, хотя любые другие последующие спецификаторы формата будут по-прежнему приводить к тому, что данные будут помещены в буфер после NUL, которые будут невидимы для стандартные функции обработки строк. Это может быть полезно, если в конечном итоге массив не должен интерпретироваться как строка C.

Я могу рискнуть утечками памяти или другими проблемами, если я, например. запустите этот NULL в точке в std :: string.c_str()?

Это совершенно непонятно, что вы имеете в виду, но если вы предлагаете, используя указатель, возвращаемый std::string.c_str() в качестве буфера для sprintf(); нет! c_str() возвращает const char*, изменение строки с помощью такого указателя не определено. Это, однако, другая проблема, а вовсе не связанная с введением NUL в строку.

Каковы наилучшие способы избежать этого оговорки (дезинфицировать вход?)

Я изо всех сил пытаюсь придумать обстоятельство, в котором вы могли бы «случайно» написать такой код, так зачем вам его защищать !? У вас есть особое обстоятельство? Несмотря на то, я считаю, это неправдоподобно, и, вероятно, нет необходимости, что так трудно о:

if(c != 0) 
{ 
    printf("%c", c) ; 
} 

или, возможно, более полезно (так как есть и другие символы, которые Вы могли бы хотеть, чтобы избежать на выходе)

if(isgraph(c) || isspace(c)) 
{ 
    printf("%c", c) ; 
} 

который будет выводить только видимые символы и пробелы (пробел, '\t', '\f', , '\n', '\r').

Обратите внимание, что вы могли бы также рассмотреть isprint(), а не isgraph(c) || isspace(c), но это исключает '\t', '\f', , '\n' и '\r'

8

Любой функцию, которая принимает стандартная строка C не остановится на первом нулевой, независимо от того, как он туда попал.

Когда вы используете% c в формате и используете 0 для символьного значения, он вставляет нуль в вывод. printf выведет нуль как часть вывода. sprintf также вставляет нуль в строку результатов, но строка, как представляется, заканчивается в тот момент, когда вы передаете вывод другой функции.

В std :: string будет содержаться нуль в пределах его содержимого, но когда вы возьмете метод c_str, чтобы передать его функции, см. Выше ответ.

+0

Несмотря на то, что это отмечено как отредактированное мной, я на самом деле просто вернул его в оригинал после случайного редактирования его вместо моей собственной записи. Сожалею. (и я получаю «очищающий» значок за свою собственную некомпетентность !?) – Clifford

3

printf() и sprintf() будет продолжаться мимо '\0' характера, вставленного с %c, потому что их выход определяется в условия содержания строки формата и %c не обозначают конец строки формата.

Включает в себя их счет; таким образом:

sprintf(x, "A%cB", '\0') 

всегда должен возвращать 3 (хотя strlen(x) впоследствии будет возвращать 1).

Смежные вопросы