Passing too many arguments to printf

前端 未结 5 980
不思量自难忘°
不思量自难忘° 2020-11-30 10:56

Any C programmer who\'s been working for more than a week has encountered crashes that result from calling printf with more format specifiers than actual argume

相关标签:
5条回答
  • 2020-11-30 11:16

    printf is designed to accept any number of arguments. printf then reads the format specifier (first argument), and pulls arguments from the argument list as needed. This is why too few arguments crash: the code simply starts using non-existent arguments, accessing memory that doesn't exist, or some other bad thing. But with too many arguments, the extra arguments will simply be ignored. The format specifier will use fewer arguments than have been passed in.

    0 讨论(0)
  • 2020-11-30 11:19

    Comment: both gcc and clang produce warnings:

    $ clang main.c 
    main.c:4:29: warning: more '%' conversions than data arguments [-Wformat]
      printf("Gonna %s and %s, %s!", "crash", "burn");
                               ~^
    main.c:5:47: warning: data argument not used by format string 
                          [-Wformat-extra-args]
      printf("Gonna %s and %s!", "crash", "burn", "dude");
             ~~~~~~~~~~~~~~~~~~                   ^
    2 warnings generated.
    
    0 讨论(0)
  • 2020-11-30 11:24

    Online C Draft Standard (n1256), section 7.19.6.1, paragraph 2:

    The fprintf function writes output to the stream pointed to by stream, under control of the string pointed to by format that specifies how subsequent arguments are converted for output. 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. The fprintf function returns when the end of the format string is encountered.

    Behavior for all the other *printf() functions is the same wrt excess arguments except for vprintf() (obviously).

    0 讨论(0)
  • 2020-11-30 11:26

    All the arguments will be pushed on the stack and removed if the stack frame is removed. this behaviour is independend from a specific processor. (I only remember a mainframe which had no stack, designed in 70s) So, yes the second example wont't fail.

    0 讨论(0)
  • 2020-11-30 11:33

    You probably know the prototype for the printf function as something like this

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

    A more complete version of that would actually be

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

    The __cdecl defines the "calling convention" which, along with other things, describes how arguments are handled. In the this case it means that args are pushed onto the stack and that the stack is cleaned by the function making the call.

    One alternative to _cdecl is __stdcall, there are others. With __stdcall the convention is that arguments are pushed onto the stack and cleaned by the function that is called. However, as far as I know, it isn't possible for a __stdcall function to accept a variable number of arguments. That makes sense since it wouldn't know how much stack to clean.

    The long and the short of it is that in the case of __cdecl functions its safe to pass however many args you want, since the cleanup is performed in the code makeing the call. If you were to somehow pass too many arguments to a __stdcall function it result in a corruption of the stack. One example of where this could happen is if you had the wrong prototype.

    More information on calling conventions can be found on Wikipedia here.

    0 讨论(0)
提交回复
热议问题