问题
I have read this post. But when I tried:
printf("before null %c after null\n", 0); // (ASCII=0) != '\0' ??
instead of getting:
before null
I got:
before null after null
So my question is: Is ASCII value 0 actually equal to '\0'?
回答1:
Is ASCII value 0 actually equal to
\0
?
Yes
The differences in how the strings are stored in memory and handled by functions like printf()
are important.
"before null %c after null\n"
"before null \0 after null\n"
Both are stored in memory with an implicit \0
terminator at the end. The fact that the second has an explicit \0
character in the middle changes things.
printf()
will scan the string until "the end", printing components as it goes... in C "the end" typically means until the first \0
/ nul character.
With the first variant, printf()
copies characters to the output until it reaches the %c
directive, at which point it looks at the arguments that were given to the function... it might find that you gave '\0'
, or it might find that you gave '+'
- either way, it copies this to the output. It'll then continue copying characters to the output, seeking "the end" of the string.
With the second variant, printf()
will start copying characters to the output, will find "the end" (denoted by the \0
), and stop.
If you were to use snprintf()
, then the results / outputs would contain the following: (again, with implicit \0
termination)
"before null \0 after null\n"
"before null "
If you were to subsequently print both of these, they would look the same, but the memory content would be different.
However, the output of printf()
is the terminal (or a file)... what happens for \0
depends on your terminal emulator... it might simply not be shown, it might be displayed as a space, or it may have a funny box symbol...
The important thing to note, is that this occurs at run time - not compile time.
回答2:
The reason is that printf
isn't actually replacing "Hello %s", "World"
with "Hello World"
then prints them all. Instead, It prints "Hello "
then "World"
in a row each character solo, In order
If you ever tried to print a single null
character using putchar()
, You'd notice that it prints a space instead, that's why printf
prints a space too based on it.
Note that It'll print nothing on other systems (e.g Linux).
Sample code of how printf actually work.
const char * x;
// while the current char != '\0'
while (*format)
{
// if the current char == '%'
if (*format == '%')
{
// increment the pointer so we can point to the next char and skip printing '%'
switch (*(++format)) // then switch that next char (specifier).
{
case 'c':
putchar(va_arg(args, char)); // if the argument is null, then it's putchar(0);
break;
case 's':
// regular operation of printing a string argument.
x = va_arg(args, const char*);
while (*x) putchar(*x++);
break;
}
// skips the format specifier so we don't print it (e.g 's', 'c'..)
*format++;
}
// else: isn't a format specfier.
else
// print the current char (pointer) of the original string
putchar(*format++); // increments it for the next operation.
}
va_end(args);
So returning to your question, It will print each character and when it comes to the argument 0
which is null, putchar()
will either put a space or nothing based on your system.
You can say that printf
arguments aren't really have any relationship with the original string to terminate it, they don't know each other.
like when you printf("Hello %s, from SO!", "World");
, "World"
is actually terminated at the end with \0
, but it will terminate just itself, not the other , from SO!
.
Yes, 0
is '\0'
. they're the same character.
回答3:
printf
will not terminate the printf format-string at that character position for the %c
format-specifier when given values 0
or '\0'
. Instead, the terminal output for the nul
will generally be a placeholder (e.g. a space
or the like)
However you can insert a nul
into the string and then output the string using the %s
format-specifier and see that in fact decimal 0 is actually the ASCII value for the equivalent ASCII character '\0'
and will terminate the string at the point of the nul-character (see: www.ASCIItable.com), e.g.
#include <stdio.h>
#define FMT "before null %c after null\n"
int main (void) {
char buf[sizeof FMT * 2];
puts (FMT);
sprintf (buf, FMT, 0);
printf ("using 0 : '%s'", buf);
putchar ('\n');
sprintf (buf, FMT, '\0');
printf ("using \\0: '%s'", buf);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/str_printf_null
before null %c after null
using 0 : 'before null '
using \0: 'before null '
来源:https://stackoverflow.com/questions/50771351/ascii-value-0-and-0