printf() with no arguments in C compiles fine. how

2019-01-19 18:54发布

I tried the below c program & I expected to get compile time error, but why compiler isn't giving any error?

#include <stdio.h>
int main(void)
{
    printf("%d\n");
    return 0;
}

Why output is compiler dependent? Here is the output on various compilers

Output on Orwell Dev C++ IDE (uses gcc 4.8.1) : 0

Output on Visual C++ provided by Visual Studio 2010 : 0

CodeBlocks IDE (uses gcc 4.7.1) : garbage value

Online compiler ideone.com : garbage value

What is going wrong here ?

10条回答
叛逆
2楼-- · 2019-01-19 19:08

Because of how C variadic arguments work, the compiler cannot track their correct usage. It is still (syntactically) legal to provide less, or more, parameters that the function needs to work, although this generally ends up as undefined behavior when looking at the standard.

The declaration of printf looks like this:

int printf(const char*, ...);

The compiler only sees ..., and knows that there may be zero or more additional arguments that the function may or may not use. The called function does not know how many arguments it is passed; it can, at best, assume that it was passed all the information it needs and nothing more.

Contrast this with other languages, like C#:

void WriteLine(string format, params object[] arguments);

Here, the method knows exactly how many additional arguments is was passed (doing arguments.Length).

In C, variadic functions and especially printf are a frequent cause of security vulnerabilities. Printf ends up reading raw bytes from the stack, which may leak important details about your application and its security environment.

For this reason, Clang and GCC support a special extension to validate printf formats. If you use an invalid format string, you'll get a warning (not an error).

code.c:4:11: warning: more '%' conversions than data arguments [-Wformat]
    printf("%d\n");
           ~~^
查看更多
Deceive 欺骗
3楼-- · 2019-01-19 19:08

This compiles well. Because it matches the printf() prototype which is

printf(const char *,...);

During run-time the call

printf("%d\n");

Tries to fetch the value from second argument and since you have not passed anything it might get some garbage value and print it out so the behavior is undefined here.

查看更多
手持菜刀,她持情操
4楼-- · 2019-01-19 19:08

In general diagnostic messages (you may think of them like compilation errors) are not guaranteed for undefined behaviors (like lack of sufficient arguments for printf function call as in your case), that are not counted as syntax rule or constraint violations.

C11 (N1570) §5.1.1.3/p1 Diagnostics:

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances.9)

In other words your compiler is free to translate such unit, but you should never run it or rely on its behaviour (as it's de facto unpredictable). Moreover your compiler is allowed not to provide any documentation (that is C Standard does not enforce it to do so), like it's required for implementation-defined or locale-specific behaviours.

C11 (N1570) §3.4.3/p2 undefined behavior:

NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

查看更多
贪生不怕死
5楼-- · 2019-01-19 19:08

In the context of printf() and fprintf(), as per C standard C11 clause 7.21.6.1, "If there are insufficient arguments for the format, the behavior is undefined. If the format is exhausted while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored."

查看更多
地球回转人心会变
6楼-- · 2019-01-19 19:09

You are invoking undefined behaviour. That's your problem, not the compiler's, and basically anything is "allowed" to happen.

Of course, virtually every existing compiler should be able to warn you about this particular condition regarding printf(), you just have to allow him to (by enabling, and heeding, compiler warnings).

查看更多
Evening l夕情丶
7楼-- · 2019-01-19 19:12

This is simply undefined behavior if you do not provide the sufficient arguments to printf, which mean the behavior is unpredictable. From the draft C99 standard section 7.19.6.1 The fprintf function which also covers printf for this case:

If there are insufficient arguments for the format, the behavior is undefined.

Since printf is a variadic function there is no matching of arguments to the function declaration. So the compiler needs to support support format string checking which is covered by -Wformat flag in gcc:

Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense. This includes standard functions, and others specified by format attributes (see Function Attributes), [...]

Enabling sufficient compiler warnings is important, for this code gcc using the -Wall flag tells us (see it live):

 warning: format '%d' expects a matching 'int' argument [-Wformat=]
 printf("%d\n");
 ^
查看更多
登录 后发表回答