Printf ("...% c ...", '\ 0') and family - what happens?

How do the various functions that take a printf format string behave given a given format value %c

\0

/ NULL

? How should they behave? It's safe? Is it defined? Is it compiler specific?

eg. sprintf()

- does it truncate the result string to NULL? How long will it return?

Will it printf()

output the entire format string or just up to a new NULL value?

Will it affect va_args

+ vsprintf

/ vprintf

? If so, how?

I can risk memory leaks or other problems if I, for example. run this NULL at the point of std :: string.c_str ()?

What are the best ways to avoid this caveat (sanitize the entrance?)

+2


a source to share


3 answers


What happens when you output NUL depends on the output device.

This is a non-printable character, i.e. isprint('\0') == 0

; therefore, it has no discernible effect on output to the display device. However, when redirected to a file (or when called fprintf()

), it inserts a NUL (zero byte) into the file; the meaning of this will depend on how the file is used.

When outputted to line C, it will be interpreted as a line terminator by standard line processing functions, although any other subsequent format specifiers will still cause the data to be placed in a buffer after a NUL, which will not be visible to standard line processing functions. This can be useful if ultimately the array is not to be interpreted as a C string.

I can risk memory leaks or other problems if I, for example. run this NULL at the point of std :: string.c_str ()?

It's not clear what you mean by this, but if you suggest using a pointer returned std::string.c_str()

as a buffer for sprintf()

; no! c_str()

returns a const char*

, modifying the string with such an undefined pointer. This, however, is a different problem, and not at all related to the introduction of NUL into the string.

What are the best ways to avoid this caveat (sanitize the entrance?)



I'm struggling to come up with a circumstance in which you could "accidentally" write such code, so why would you protect it !? Do you have a special circumstance? While I find it implausible and probably unnecessary, it's so hard:

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

      

or perhaps more useful (as there are other characters you might want to avoid in the output)

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

      

which displays only the visible characters and spaces (space, '\t'

, '\f'

, '\v'

, '\n'

, '\r'

)).

Please note that you may also consider isprint()

, instead isgraph(c) || isspace(c)

, but it eliminates the '\t'

, '\f'

, '\v'

, '\n'

and'\r'

+3


a source


Any function that accepts a standard C string will stop at the first zero, no matter how it got there.

When you use% c in format and use 0 for a character value, it inserts zero into the output. printf

prints zero as part of the output. sprintf

also inserts zero in the resulting string, but the string will end at that point when you pipe the output to another function.



A std :: string will happily contain null anywhere in its content, but when you take the c_str method to pass it to a function, see the answer above.

+8


a source


printf()

and sprintf()

will continue after the character '\0'

inserted with %c

, because their output is defined in terms of the contents of the format string, and %c

does not denote the end of the format.

This includes their number; In this way:

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

      

should always return 3 (although strlen(x)

it will return 1 afterwards).

+3


a source







All Articles