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

前端 未结 10 1948
后悔当初
后悔当初 2020-12-02 00:10

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

#include 
int main(void)
{
          


        
相关标签:
10条回答
  • 2020-12-02 00:51

    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).

    0 讨论(0)
  • 2020-12-02 00:52

    what warnings/messages did you get using your compilers? i ran this through gcc (Ubuntu 4.8.2-19ubuntu1) and got a warning

    warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat=]
         printf("%d\n");
         ^
    

    and running it also "garbage output". here, the gcc is so clever to parse the format expression and notifies the coder to provide a matching number of arguments.

    what i think happens: the function signature of printf is independent from the behaviour of the compiled code. at compile time, all the compiler cares is to check if at least one argument is there and continues. however, the compiled function will first parse the format expression and, dependent on that, read further arguments from the functions' arguments stack. therein it simply expects appropriately put values (int, float etc) and uses them. so if you dont specify the argument, no place on the function call stack is reserved and printf still reads random memory (in this case at the first location). this also explains the "garbage" output, which will differ each time you call the binary. you can even extend the code to

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

    and get two different garbage numbers :)

    then again it will depend on the environment/process/compiler which values will be read. "unspecified behaviour" is what describes this effect best, sometimes zero, sometimes other.

    i hope this clarifies your issue!

    0 讨论(0)
  • 2020-12-02 00:53

    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).

    0 讨论(0)
  • 2020-12-02 00:53

    According to this documentation, the additional arguments must be at least as many as the format specifiers in the first argument. This seems to be undefined behaviour.

    0 讨论(0)
  • 2020-12-02 00:54

    Using g++ with commandline parameter -Wall produces the following diagnostics:

    g++ -Wall   -c -g -MMD -MP -MF "build/Debug/MinGW-Windows/main.o.d" -o build/Debug/MinGW-Windows/main.o main.cpp
    main.cpp: In function 'int main(void)':
    main.cpp:17:16: warning: format '%d' expects a matching 'int' argument [-Wformat=]
         printf("%d");
                    ^
    

    That's pretty useful, isn't it?

    gcc/g++ also check if the format specifiers actually match the parameter types. This is really cool for debugging.

    0 讨论(0)
  • 2020-12-02 01:00

    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");
     ^
    
    0 讨论(0)
提交回复
热议问题