What is the difference between %d and %*d in c language? - c

What is %*d ? I know that %d is used for integers, so I think %*d also must related to integer only? What is the purpose of it? What does it do?
int a=10,b=20;
printf("\n%d%d",a,b);
printf("\n%*d%*d",a,b);
Result is
10 20
1775 1775

The %*d in a printf allows you to use a variable to control the field width, along the lines of:
int wid = 4;
printf ("%*d\n", wid, 42);
which will give you:
..42
(with each of those . characters being a space). The * consumes one argument wid and the d consumes the 42.
The form you have, like:
printf ("%*d %*d\n", a, b);
is undefined behaviour as per the standard, since you should be providing four arguments after the format string, not two (and good compilers like gcc will tell you about this if you bump up the warning level). From C11 7.20.6 Formatted input/output functions:
If there are insufficient arguments for the format, the behavior is undefined.
It should be something like:
printf ("%*d %*d\n", 4, a, 4, b);
And the reason you're getting the weird output is due to that undefined behaviour. This excellent answer shows you the sort of things that can go wrong (and why) when you don't follow the rules, especially pertaining to this situation.
Now I wouldn't expect this to be a misalignment issue since you're using int for all data types but, as with all undefined behaviour, anything can happen.

When used with scanf() functions, it means that an integer is parsed, but the result is not stored anywhere.
When used with printf() functions, it means the width argument is specified by the next format argument.

The * is used as an indication that the width is passed as a parameter of printf

in "%*d", the first argument is defined as the total width of the output, the second argument is taken as normal integer.
for the below program
int x=6,p=10;
printf("%*d",x,p);
output: " 10"
the first argument ta passed for *, that defines the total width of the output... in this case, width is passed as 6. so the length of the entire output will be 5.
now to the number 10, two places are required (1 and 0, total 2). so remaining 5-2=3 empty string or '\0' or NULL character will be concatenated before the actual output

Related

Why is printf() printing out in this code?

This simple code is puzzling me - I am deliberately printing out more integers than I passed to printf. I expected an error. I got weird numbers - where are they coming from?
#include <stdio.h>
/* learn arrays */
void main(){
int pout;
pout = 6;
printf("%i %i %i\n%i %i %i\n%i %i %i\n", pout);
}
One example of the output:
6 608728840 0
-885621664 -885543392 608728816
0 0 -889304251
The single digits do not change with repeated runs, but the large integers do.
It's one of printf string format vulnerability. You are trying to call more argument than there actually are, so printf takes whatever he can on the stack.
It was (and still is) very used to exploit programs into exploring stacks to access hidden information or bypass authentication for example.
Viewing the stack
printf ("%08x %08x %08x %08x %08x\n");
This
instructs the printf-function to retrieve five parameters from the
stack and display them as 8-digit padded hexadecimal numbers. So a
possible output may look like:
40012980 080628c4 bffff7a4 00000005 08059c04
See this for a more complete explanation.
Because it's undefined behavior. If the number of specifiers is larger than the number of matching parameters or their types are incompatible, the behavior is undefined.
This qoute is from the c11 standard draft
7.21.6.1 The fprintf function
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.
If a conversion specification is invalid, the behavior is undefined.282) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
I highlighted the relevant parts making them bold.
The int reserves some RAM but you didn't wrote anything in so it shows you what numbers are random somewhere in your RAM

why array shows garbage value when only one format specifier used?

i am trying to print value of an array in C-language.I am using 3 format specifier for only one value of array , my problem is that i don't understand that how other two values are coming in my output .
here is my code:
int arr[6] = {3,4,42,2,77,8};
printf("%d %d %d ",arr[2]);
output :
42 3 4
According to the C Standard
If there are insufficient arguments for the format, the behavior is
undefined.
In your call of printf
printf("%d %d %d ",arr[2]);
the arguments are exhausted after the first format specjfjer. So the function call has undefined behaviour and the output can contain any garbage.
You shall write
printf( "%d ", arr[2] );
or for example
printf( "%d %d %d ", arr[2], arr[3], arr[4] );
When printf() sees three format specifiers, it looks at specific locations, either in stack memory or in CPU registers, depending on the conventions of the compiler, for three arguments.
You provided one, but some data that you have no control over exists in the other two locations, and that's what gets printed.
The other two values are garbage and don't have any meaning. The function printf requires as many arguments as there are format specifiers, so in your case three. Since you only provided one argument (arr[2]), the other two specifier 'don't know' what to print - thus gargabe will come out. Make sure to provide the required number of arguments.
If you want to print the array number by number, you will have to use a for loop.
The signature of printf is.
int printf(char*, ...);
So, you can have a variable number of arguments, then.
printf("%d %d %d ",arr[2]);
Is a valid call of the function printf.
However, because you provided no values ​​yourself, then you will get whatever... that in your special case it seems that it printed arr[0] and arr[1].

Why does the strange value come out with an unnecessary % conversion in the code in C language?

I started learning programming only few days ago, so basically I have no knowledge.
I'm starting with C, and I wrote a very simple code which is:
int main (int argc, const char * argv[])
{
printf("%d + %d", 1 + 3);
return 0;
}
with the code above, I got the value of 4 + 1606416608 and later found that the return value is wrong because I put more %d than necessary. Then my question is, how did that strange value actually come out? If anyone knows, please help me. Thank you!!
You know what you did wrong already, so to explain what your particular implementation of C probably did:
When you call printf, a new stack frame is pushed to the call stack. The call stack is a last in first out structure with one 'frame' per called function. So if main called logStuff which called printf then three consecutive frames would be for main, then logStuff, then printf. When printf returns, it's frame is removed from the structure and execution continues with logStuff.
So a frame usually contains at least the parameters passed to the function and storage for local variables. Those things may be one and the same, it's implementation dependant.
With a variadic function like printf there's a stream of unnamed parameters. The bit patterns will be put into an appropriate place in the frame. But C is not a reflective language. Each bit patten doesn't inherently have a meaning: any one could be an integer, a float, or anything else. It also isn't a language that invests in bounds checking. You're trusted to write code that acts correctly.
printf determines the types and number of unnamed parameters from the string. So if you've given it false information, it will interpret the bit patterns with something other than their correct meaning and it may think there are fewer or more than are really there.
You told it there were more. So what probably happened was that the parameters were in the equivalent of an array and it read a value from beyond the end of the array. As it's all implementation dependent, that value may have been meant to represent anything. It could be the address of the caller. It could be uninitialised storage for another local variable. It could be bookkeeping. It could be the format string, incorrectly interpreted as an integer.
What it isn't is any reliable value. It may not even always be safe to read.
You are in undefined behavior land... you are telling a variadic function that you have 2 int sized params, then you only supply one, you are leaking something from the stack.
1) %d is a format specifier, it tells the compiler how you want to access the value stored at a particular location.(here as an integer)
2) For every format specifier you need to provide a corresponding variable or a value, otherwise at runtime you will get "garbage" i.e. some random value.
Example :
int main()
{
int a = 65;
printf("\na = %d", a); // here the value stored in a is accessed as an integer.
printf("\na = %c", a); // the value inside a is accessed as a character.
return 0;
}
In the above example '%d' in the first printf statement tells the compiler that the value stored in the variable a is to be accessed as an integer. (o/p - 65)
In the second printf statement '%c' is used to access the same variable as a character.(o/p - A)
Your code expects two numerical parameters to be printed, and you're giving it one.
Expected:
printf("%d + %d", <some_num>, <another_num>);
You're giving it:
printf("%d + %d", <some_num>);
Where <some_num> is what 1+3 evaluates to. The function expects another argument, but receives garbage instead.
What you should do is
printf("%d + %d = %d", 1, 3, 1+3);

C variable assignment issue

I think the title does not suit well for my question. (I appreciate it, if someone suggests an Edit)
I am learning C with "Learn C The Hard Way.". I am using printf to output values using format specifiers. This is my code snippet:
#include <stdio.h>
int main()
{
int x = 10;
float y = 4.5;
char c = 'c';
printf("x=%d\n", x);
printf("y=%f\n", y);
printf("c=%c\n", c);
return 0;
}
This works as I expect it to. I wanted to test it's behavior when it comes to conversion. So everything was ok unless I made it to break by converting char to float by this line:
printf("c=%f\n", c);
Ok, I'm compiling it and this is the output:
~$ cc ex2.c -o ex2
ex2.c: In function ‘main’:
ex2.c:13:3: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]
printf("c=%f\n", c);
^
The error clearly tells me that It cannot convert from int to float, But this does not prevent the compiler from making an object file, and the confusing part is here, where I run the object file:
~$ ./ex2
x=10
y=4.500000
c=c
c=4.500000
As you can see printf prints the last float value it printed before. I tested it with other values for y and in each case it prints the value of y for c. Why this happen?
Your compiler is warning you about the undefined behaviour you have. Anything can happen. Anything from seeming to work to nasal demons. A good reference on the subject is What Every C Programmer Should Know About Undefined Behavior.
Normally, int can convert to double just fine:
int i = 10;
double d = i; //works fine
printf is a special kind of function. Since it can take any number of arguments, the types have to match exactly. When given a char, it is promoted to int when passed in. printf, however, uses the %f you gave it to get a double. That's not going to work.
Here is how one would implement their own variadic function, taken from here:
int add_nums(int count, ...)
{
int result = 0;
va_list args;
va_start(args, count);
for (int i = 0; i < count; ++i) {
result += va_arg(args, int);
}
va_end(args);
return result;
}
count is the number of arguments that follow. There is no way for the function to know this without being told. printf can deduce it from the format specifiers in the string.
The other relevant part is the loop. It will execute count times. Each time, it uses va_arg to get the next argument. Notice how it gives va_arg the type. This type is assumed. The function needs to rely on the caller to pass in something that gets promoted to int in order for the va_arg call to work properly.
In the case of printf, it has a defined list of format specifiers that each tell it which type to use. %d is int. %f is double. %c is also int because char is promoted to int, but printf then needs to represent that integer as a character when forming output.
Thus, any function that takes variadic arguments needs some caller cooperation. Another thing that could go wrong is giving printf too many format specifiers. It will blindly go and get the next argument, but there are no more arguments. Uh-oh.
If all of this isn't enough, the standard explicitly says for fprintf (which it defines printf in terms of) in C11 (N1570) §7.21.6.1/9:
If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
All in all, thank your compiler for warning you when you are not cooperating with printf. It can save you from some pretty bad results.
Since printf is a varargs function, parameters cannot be converted automatically to the type expected by the function. When varargs functions are called, parameters undergo certain standard conversions, but these will not convert between different fundamental types, such as between integer and float. It's the programmer's responsibility to ensure that the type of each argument to printf is appropriate for the corresponding format specifier. Some compilers will warn about mismatches because they do extra checking for printf, but the language doesn't allow them to convert the type -- printf is just a library function, calls to it must follow the same rules as any other function.
Here is a very general description, which may be slightly different depending on the compiler in use...
When printf("...",a,b,c) is invoked:
The address of the string "..." is pushed into the stack.
The values of each of the variables a, b, c are pushed into the stack:
Integer values shorter than 4 bytes are expanded to 4 bytes when pushed into the stack.
Floating-point values shorter than 8 bytes are expanded to 8 bytes when pushed into the stack.
The Program Counter (or as some call it - Instruction Pointer) jumps to the address of function printf in memory, and execution continues from there.
For every % character in the string pointed by the first argument passed to function printf, the function loads the corresponding argument from the stack, and then - based on the type specified after the % character - computes the data to be printed.
When printf("%f",c) is invoked:
The address of the string "%f" is pushed into the stack.
The value of the variable c is expanded to 4 bytes and pushed into the stack.
The Program Counter (or as some call it - Instruction Pointer) jumps to the address of function printf in memory, and execution continues from there.
Function printf sees %f in the string pointed by the first argument, and loads 8 bytes of data from the stack. As you can probably understand, this yields "junk data" in the good scenario and a memory access violation in the bad scenario.

What's the standard definition of printf in C?

What is the function definition of the printf() function as defined in the standard C library?
I need the definition to solve the following question:
Give the output of the following:
int main()
{
int a = 2;
int b = 5;
int c = 10;
printf("%d ",a,b,c);
return 0;
}
The C language standard declares printf as follows:
int printf(const char *format, ...);
It returns an integer and takes a first parameter of a pointer to a constant character and an arbitrary number of subsequent parameters of arbitrary type.
If you happen to pass in more parameters than are required by the format string you pass in, then the extra parameters are ignored (though they are still evaluated). From the C89 standard §4.9.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.
You pass an array of chars (or pointer) as the first argument (which includes format placeholders) and additional arguments to be substituted into the string.
The output for your example would be 2 1 to the standard output. %d is the placeholder for a signed decimal integer. The extra space will be taken literally as it is not a valid placeholder. a is passed as the first placeholder argument, and it has been assigned 2. The extra arguments won't be examined (see below).
printf() is a variadic function and only knows its number of additional arguments by counting the placeholders in the first argument.
1 Markdown does not allow trailing spaces in inline code examples. I had to use an alternate space, but the space you will see will be a normal one (ASCII 0x20).
Its
int printf(const char *format, ...);
format is a pointer to the format string
... is the ellipsis operator , with which you can pass variable number of arguments, which depends on how many place holders we have in the format string.
Return value is the number of characters that were printed
Have a look here about the ellipsis operator: http://bobobobo.wordpress.com/2008/01/28/how-to-use-variable-argument-lists-va_list/
man 3 printf gives...
int printf(const char *restrict format, ...);
Writes to the standard output (stdout) a sequence of data formatted as the format argument specifies. After the format parameter, the function expects at least as many additional arguments as specified in format.
%d = Signed decimal integer
printf("%d ",a,b,c);
For every %(something) you need add one referining variable, therefore
printf("%d ",a+b+c); //would work (a+b+c), best case with (int) before that
printf("%d %d %d",a,b,c); //would print all 3 integers.

Resources