问题
I'm creating a modified printf implementation, and I'm not sure about the answers to these questions.
Does zero work as a null string? (Is
printf("%s", 0)
allowed?)I'm guessing no, because 0 is an
int
. But then this prompts this question:Does
NULL
work as a null string? (Isprintf("%s", NULL)
allowed?)Logically, I think it should be yes, because
NULL
implies a pointer; but a lot of implementations seem to have#define NULL 0
, so I feel in practice it might be no. Which is correct?Does the pointer type have to point to
char
? (Isprintf("%s", (void const *)"")
allowed?)My guess is that the type doesn't matter, but I'm not sure.
回答1:
Case 1 is undefined behavior because the type of the argument (int
) does not match the type required by the format specifier (char *
).
Case 2 is undefined behavior for the same reason. NULL
is allowed to be defined as any integer constant expression with value 0, or such an expression cast to (void *)
. None of these types are char *
, so the behavior is undefined.
Case 3 is undefined behavior for the same reason. ""
yields a valid pointer to a null-terminated character array (string), but when you cast it to const void *
, it no longer has the right type to match the format string. Thus the behavior is undefined.
回答2:
I believe it would compile just fine but behavior is undefined.
Something about how printf
works and why it is considered to be unsafe.
printf
takes as many arguments, as you give it with only one (first one) being required. All the arguments (except for the first one - the pattern) are then treated as an array of bytes. It doesn't check types or anything. It simply prints.
Printing string is more complicated as it just goes on until it finds 0 byte
('\0'). To clarify, you can try testing it with integers. As you know, short
is 2 bytes-long, long
is 4 and long long
is 8. If you told printf to print long
and passed 2 short
s - it would treat them as one long
. Or if you passed long long
and told it to print long
, it would take 4 first bytes and use them for printing.
With that in my these specific cases would probably (didn't test) print nothing but it is considered to be undefined behavior. If these values weren't 0s, it may print some characters if you passed some specific values which had a couple non-'\0'
s at the beginning.
Not quite sure if it helps but hope so.
回答3:
From the online C11 draft:
7.21.6.1 The fprintf function
...s
If nol
length modifier is present, the argument shall be a pointer to the initial element of an array of character type.280) Characters from the array are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the array, the array shall contain a null character.
280) No special provisions are made for multibyte characters.
Anything other than a pointer to the first element of an array of char
containing at least 1 character (the 0 terminator) invokes undefined behavior.
If you're building your own implementation, you can certainly define your own behavior for 0 or NULL.
Oh, and as far as the definition of NULL is concerned:
6.3.2.3 Pointers
...
3 An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
66) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.19
Basically, any 0-valued integer expression in a pointer context is considered a NULL pointer.
来源:https://stackoverflow.com/questions/12222447/a-few-questions-about-legal-arguments-to-printfs