Those pitfalls of printf

Source: Internet
Author: User

As long as you have been playing C or C ++, you must be familiar with printf. There are several methods below. Do you know what each method outputs?


void Test1(){    printf("hello %d");}void Test2(){    printf("hello %s");}void Test3(){    int a = 0;    printf("hello %s");}


It is certain that the above three methods are incorrect, but will the program crash when we are running these three methods?

To answer this question, we need to first understand how the printf function plays?

(Note: The following code is compiled and run by the VC compiler. The conclusion is only limited to this compiler. The compilation option is: in release mode, disable code optimization)

1. _ cdecl

The so-called _ cdecl, C language default call protocol, that is, the caller is used to reclaim the stack space, the parameter is from right to left pushed into the stack. (It is clear that you can pass the Agreement-related shoes directly)

Here is a description of the column:

int __cdecl my_cdecl(int a, int b, int c){    return a + b + c;}int _tmain(int argc, _TCHAR* argv[]){    my_cdecl(123, 456, 789);    return 0;}

Compilation code corresponding to the main function:

Printftest! Wmain: 010f1010 55 push EBP; EBP in-stack 010f1011 8bec mov EBP, esp; update listen 6815030000 push 315 h; 789 in-stack 010f1018 68c8010000 push 1c8h; 456 in-stack 010f101d 6a7b push 7; 123 inbound stack 010f101f e8dcffffff call printftest! My_cdecl (010f1000); call the my_cdecl function 010f1024 83c40c add ESP, 0ch; reclaim stack space, 3*4 = 33c0 XOR eax, eax010f1029 5d pop ebp010f102a C3 RET

The assembly code above verifies that the parameter is pressed from right to left-first 789, then 456, and finally 123;

And the main function is responsible for recycling the stack space -- add ESP, 0ch. The size of the three int values is exactly 12. After calling the my_cdecl function, add the top stack pointer ESP to 12, the stack balance is maintained.

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

The preceding is the declaration of the printf function. printf contains a variable parameter, that is, the number of parameters is variable. In fact, it is precisely because the _ cdecl caller recycles the stack space features that variable parameter calls can be implemented. Only the caller can know how many parameters are passed in to recycle the stack space correctly.

_ Stdcall, which is called to recycle stack space, cannot play with variable parameters.

A correct printf example

void Test(){    int a = 2014;    char* sz = "hello QQ";    printf("%s %d", sz, a);}

It's easy to know the output: Hello QQ 2014.

Let's take a look at how printf works:

0: 000> U printftest! Test l10printftest! Test [D: \ work \ test \ printftest. CPP @ 7]: 013b1000 55 push ebp013b1001 8bec mov EBP, esp; pushed; this code is used to assign a value to the local variable A and Sz 013b1003 83ec08 ESP sub, 8013b1006 c745fcde070000 mov dword ptr [ebp-4], 7deh013b100d c745f8f4203b01 mov dword ptr [ebp-8], offset printftest! Gs_exceptionpointers + 0x8 (013b20f4) 013b1014 8b45fc mov eax, dword ptr [ebp-4] 013b1017 50 push rj8b4df8 mov ECx, dword ptr [ebp-8] 013b101b 51 push ECx; ----------------------------------------------------------- 013b101c 680020.b01 push offset printftest! Gs_exceptionpointers + 0x14 (013b2100); "% S % d" Incoming stack 013b1021 ff15a0203b01 call dword ptr [printftest! _ Imp _ printf (013b20a0)]; call printf013b1027 83c40c add ESP, 0ch; reclaim stack space, three parameters, 12 bytes 013b102a 8be5 mov ESP, ebp013b102c 5d pop ebp013b102d C3 ret013b102e cc int 3

What is the status of the current thread stack in the program memory before the Code calls printf?


We can draw a conclusion: printf first extracts the formatted string from the top of the stack and parses it, according to the number of % (except %) from the top of the stack (except for the formatted string) take the parameters from top to bottom for display.

Because printf does not know the number of input parameters, it cannot determine the number of input parameters or whether the type matches the formatted string. It can only be formatted from the top of the stack (except the formatted string) the value is retrieved sequentially, regardless of whether the value is an input parameter.

Therefore, if the number or type of parameters does not match the formatted string, the running result is completely dependent on the status of the current stack.


Return to the three examples at the beginning of the question:



Those pitfalls of printf

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.