printf function allows c/c++ programmer to write formatted string to the standard output (
stdout).
Though c++ introduced a better technique to write the output data in different output channel by using stream classes like
ostream, iostream, fstream etc... but still
printf is preferred in some places by many of the programmers, because it provides an easy interface (depends programmer to programmer) to write formatted output but along with this it has some problem (if code is not compiled with
-Wformat or
-Wall) which is described below.
The declaration of
printf function is
int printf(const char* format,...);
where
format takes the const string/format-specifiers. if
format contains any format specifier then printf function expect the corresponding data to be printed.
As per the above mentioned
printf declaration, first parameter of printf must be
const char* type and then rest can be anything. That means at the compile time compiler will only check for the first parameter and it doesn't bother about other parameters. Now consider the below example which may create problem at runtime.
*
Problem when you forgot to pass the value for specified format specifier
int a=10,b=20;
printf("value of a = %d, value of b = %d",a); //here value of b is not passed but compiler doesn't bother for that.
Output:
value of a = 10, value of b = -1074196968
here value of
b is expected as 20 but it is printing a garbage value because
b was not passed and compiler also does not throw error for this mistake.
*
Problem when you use wrong format specifier
int a=16450,b=1651;
printf("value of a = %c, value of b = %d",a,b); //here value of a is formatted by %c format specifier
Output:
value of a = B, value of b=1651
here
printf function is taking the lower 1 byte of
a, that is 66 and printing the ascii char
B.
* Problem when you use data type of more than 4 bytes and try to print with wrong format specifier
long long int x=0x4100000042;
int a=10,b=20;
printf("value of x=%d, value of a = %d, value of b = %d",x,a,b);
Output:
value of x=66, value of a = 65, value of b = 10
value of x is printed with %d format specifier where it is a
long long int type so it is taking the lower 4 byte and printing but the expected value of a and b was 10 and 20 respectively and it was printing 65 and 10....
where is the problem ?
All the data passed to the printf funtion will be pushed into a stack, and it will be processed by using
va_list, now suppose a
long long int value which is 8 byte is passed to the printf funtion but format specifier is given
%d that is to print integer value (a 4 byte data). So printf will take 4 byte value from stack and print.
In the above example value will be pushed as
MSB << [
0x00000014 |
0x0000000a |
0x00000041 |
0x00000042] << LSB
<
------ b ----> <
-----a -----> <
-------------- x --------------->
- while printing "x=%d" , it will take first 4 bytes (from LSB) because format specifier is "%d", first 4 bytes data is 0x00000042 = 66. So it is printing "value of x = 66".
- while printing "a = %d", it will take next 4 bytes (from LSB) because format specifier is "%d", next 4 bytes data is 0x00000041 = 65, so it is printing "value of a = 65"
- while printing "b = %d", it will take next 4 bytes (from LSB) because format specifier is "%d", next 4 bytes data is 0x0000000a = 10, so it is printing "value of b = 10".
Since no other format specifiers is present now so it will stop printing the data, but you can see one data is still there in memory which is not yet printed, so if one more format specifier is given then the remaining data also should be printed, like:
long long int x=0x4100000042;
int a=10,b=20;
printf("value of x=%d, value of a = %d, value of b = %d, extra data = %d",x,a,b);
Output:
value of x=66, value of a = 65, value of b = 10, extra data = 20
NOTE: In this example there is no corresponding data for "extra data = %d".
Another example:
(few compiler will throw error for this example)