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].
Related
Keep getting the following warning: “too many arguments for format” for the printf function below. Do not know what is causing this warning. I provided the type values of pos and str_pos along with the printf function. I excluded all other code as I did not think it was necessary for this question.
int pos;
char str_pos;
printf("The character at index %d is %c",pos,str_pos, "\n");
The corect way of writing that printf() statement would be
printf("The character at index %d is %c\n", pos, str_pos);
You need to change
“ to "s.
Use the format string correctly, including the newline.
use pos and string_pos as the argument (not part of the format string itself), in the variadic list.
Also, I presume that variables are initialized before you're printing them.
Okay this is going to be somewhat lengthy.
So I've got a program that uses two %n format parameters in it's a printf() statement. %n essentially writes data without displaying anything... So when my format function encounters %n parameter, it writes the number of bites that have been written by the function to the address of the corresponding function argument.
#include <stdio.h>
#include <stdlib.h>
int main() {
int A = 5, B = 7, count_one, count_two;
printf("The number of bytes written up to this point X%n is being stored in
count_one, and the number of bytes up to here X%n is being stored in
count_two.\n", &count_one, &count_two);
printf("count_one: %d\n", count_one);
printf("count_two: %d\n", count_two);
printf("A is %d and is at %08x. B is %x.\n", A, &A, B);
exit(0);
}
the output of the program is:
The number of bytes written up to this point X is being stored in count_one,and the number of bytes up to here X is being stored in count_two.
count_one: 46
count_two: 113
A is 5 and is at bffff7f4. B is 7.
With regards to this printf
printf("A is %d and is at %08x. B is %x.\n", A, &A, B);
Now, the arguments are pushes to the stack in reverse order first the value of B then the value address of A then the value address of A, and finally the address of the format string...
Now if only two arguments are pushed to the stack with a format string that uses three format parameters?
So I removed the last argument in the code above to match this printf() argument
printf("A is %d and is at %08x. B is %x.\n", A, &A);
and what happens when I compile and execute is...
The number of bytes written up to this point X is being stored in count_one, and the number of
bytes up to here X is being stored in count_two.
count_one: 46
count_two: 113
A is 5 and is at bffffc24. B is b7fd6ff4
So I get this b7fd6ff4, what is that? What does this mean with relations to the stack frame for the format function?
Any insight or explanation would be much appreciated.
Having either the wrong number of format specifiers or mismatched format specifiers invokes undefined behavior.
From section 7.21.6.1 of the C standard regarding the fprintf function:
9 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.
What this means is that you can't make any reliable prediction about what value the function will receive if you don't pass it enough parameters. What will most likely happen in an implementation that uses a stack and has optimizations disabled is that it will grab whatever value happens to be next in memory next to the last parameter pushed onto the stack.
the following proposed code:
fixes the problems listed in the comments to the question
cleanly compiles
performs the desired functionality
and now the proposed code:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int A = 5;
int B = 7;
int count_one;
int count_two;
printf("The number of bytes written up to this point X%n is being stored"
" in count_one, and the number of bytes up to here X%n is being"
" stored in count_two.\n",
&count_one,
&count_two);
printf("count_one: %d\n", count_one);
printf("count_two: %d\n", count_two);
printf("A is %d and is at %p. B is %x.\n", A, (void*)&A, B);
exit(0);
}
a typical run of the program results in:
The number of bytes written up to this point X is being stored in count_one, and the number of bytes up to here X is being stored in count_two.
count_one: 46
count_two: 113
A is 5 and is at 0x7fff19c28ea8. B is 7.
Under the 32-bit x86 calling convention all function parameters are passed on the stack. If you call printf() with more format specifiers than arguments the function will gladly keep walking up the stack and grabbing whatever values are there to find something to display.
The specific contents of the stack are going to be variable- usually function-local variables, function return pointers, or stack pointers.
printf assumes that you pushed all 4 arguments on the stack. It is expecting B to be on the stack regardless of whether you provided it or not. If you did not provide it then it will use whatever is in that memory location and print it.
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);
Here's a quick question.
When you use format specifiers in the string you want to print, but don't list any values which you want to replace the placeholders with after the string, you get seemingly random numbers such as 2627389, 6278253 etc. as the output. Here's an example:
printf("%d %d %d");
The output would look something like:
2621244 4352722 1426724
I was wondering why this happens, and what those numbers mean. If you have an idea, it would really help.
Thanks.
In most cases, those numbers are "random" values that just happen to be in the stack or in registers depending on the processor. In the olden days, all the parameters to a function were passed on the stack, pushed in reverse order. For printf(), the first parameter, and the last pushed, would be the format string. In your example, the stack would look like:
sp[0] = "%d %d %d"
printf would grab the top of the stack (the format string) and parse it, grabbing additional parameters in higher stack locations, format them according to the format string and output them appropriately.
If you had a well formed printf call, e.g. printf("%d %d %d", 1, 2, 3), then the stack would look like
sp[3] = 3
sp[2] = 2
sp[1] = 1
sp[0] = "%d %d %d"
printf would do what you expect: grab the appropriate stack location for each format specifier and format it appropriately. When you don't pass the other parameters, whatever happens to be in those stack locations are output instead, hence the "random" values.
It's called "undefined behavior" ;)
At best, you'll get garbage. At worst, you can actually crash the program.
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