printf %f address error - c

I got a problem with printf the pointer address. I was confused with printf.Here is the code:
#include<stdio.h>
int main() {
float aa[3] = {1.0, 2.0, 3.0};
printf("%f, %f\n", aa, aa[1]);
return 0;
}
When I compiled it and got the results like this:
2.000000, 1.000000

if you want to printf the address,you should use the type of argument that is %p, not %f.

What you do is basically lying (or at least cheating) to your library. If that's intented or by accident doesn't matter.
You tell the library that you want to print a double value.
Without knowing the real type, printf fetches content for a double from the variable parameter list.
But then you put an address into parameter list which is of wrong type and wrong size.
This does not only mean that the value for this parameter is printed incorrectly, but also that a wrong number of bytes is consumed from the input.
Therefore also the second parameter can be printed incorrectly because printf is reading from the wrong address.

You can use %p for printing the address,
Here aa and &aa[0] are both same, which holds the base address of the array.
try this:
printf("%p %p",&aa[0],aa); /*Which will give you the base address of array*/
You will get the o/p in Hex format.

Related

Why do we feed an adress to scanf?

So in the following snippet, we ask the user to assign some value to our integer x.
int x;
scanf("%d", &x);
What I'm confused about is why we're saying "put the value of the input into the adress of x", instead of just "let x be equal to the value of the input"? What would be the problem with scanf("%d", x)?
In C, parameters are passed by value. So if you use x as a parameter to scanf, it just gets a copy of the value of x, it doesn't get a reference to the actual variable x.
By passing a pointer, you're giving it the address of the memory that the x variable's value is stored in. That allows scanf to modify the value of x by storing into that memory.
All function calls take their arguments by value. Passing x would just give scanf a copy of x, and it still wouldn't have access to our x.
Taking the address of a variable produces a pointer, which when copied, still points to the same variable. Thus scanf can dereference its copy of the pointer and gain access to x.
Short answer: because you have to. The specification of scanf says that for the format specifier %d it expects the corresponding argument to have the type int *, which means &x, not x.
C doesn't have pass-by-reference. scanf is a function like any other and when you pass a variable to it, you don't pass the variable itself, but its value. So when you call scanf("%d", x); you give it the (uninitialized) value of x, which is useless to scanf. When you pass the address of x, scanf can put the value it scanned into x by dereferencing it.
As n.m. commented, calling scanf("%d", x); is (somewhat) equivalent to calling scanf("%d", 5); (or more accurately: scanf("%d", <garbage>);). It can't assign to a constant, or an ordinary number, but it can assign to the place that a (valid) address points to.
I'm just going to take a slightly different approach and try and make you answer the question for yourself.
Consider the following code (that won't compile but supposes that you only need to do as you suggest and call scanf("%d", x)):
int w = 5;
int x = 5;
int y = 5;
int z = 5;
scanf("%d", x);
When you make the call to scanf, scanf doesn't know that you have passed the value of x, all it knows is that you have given it a value of 5, just as if you had written the line scanf("%d", 5)
Assuming you were the programmer who was coding scanf, if you've been given the parameters "%d" and 5, which of the variables w, x, y or z would you update? How would you even know that the variables w, x, y, z exist? How would you know that there aren't any other variables in the code with the value of 5? How would you know that the value of 5 you have received actually came from the variable x?

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);

Address Of String Literals in C

I have read that the type of string literal is char[n+1], where n is the length.The storage of string literals is an implementation issue.But still it must be unique at an instant.
printf
("%u\t %s\t %d\t %c\t %f\t %e\t %x\t %p\t",
&"XY",&"XY",&"XY",&"XY",&"XY",&"XY",&"XY",&"XY");
The output of this code is
4206628 XY 4206628 $ 0.000000 1.800980e-307 7ffde000 00000032
Why %f gives zero, %s gives XY (no effect of &?), and %p gives a totally different value?
You cannot pass values of the wrong type (a type that doesn't match what the formatting specifier says is expected) and not get undefined behavior.
For instance, it's quite possible that a double which is what %f expects is bigger than a pointer (which is what you're actually) passing, thus leading to a mis-match between the passed values and the values consumed by printf(), and more or less mayhem as a result.
Why %f gives zero?
Because %f expects a double while it's not, this leads to undefined behavior.
%s gives XY (no effect of &?)
Possibly because for an array arr: arr and &arr have the same value. However, the type is different, which means you are passing the unexpected type to printf, again, undefined behavior.
and %p gives a totally different value?
That's the pointer value you are looking for.

scanf crashes when trying to read a float into an array

This is my code:
double values[8], cumulative[8];
printf("Enter first decimal number: ");
scanf("%f", values[0]);
printf("values[0] = %g", values[0]);
My problem is that the scanf statement crashes the program, and the second printf is never executed. My original attempt was to fill each slot of the array with a double, but since that didn't work I simplified the program to this, but this doesn't work either.
I'm a beginner learning C, so I probably made a stupid mistake I just can't see. Any help would be appreciated, thanks!
Edit:
Okay, so apparently I need to add an ampersand to the scanf statement. But I thought an array was just a pointer to the first element of the array? Why do I have to use the ampersand?
scanf("%f", values[0]); - Here address of first element should be passed to scanf. You are passing value of first element which is a garbage value so that it crashed.
values[0] is *(values + 0), so this will give value of the first element not the address of the first element.
Do scanf("%lf", &values[0]); or scanf("%lf", (values + 0)); or scanf("%lf", values);
As it is double use %lf instead of %f.
One more problem in your program is uninitlized variables. Try to initialize the variable to zero while declaring.
double values[8] = {0};
double cumulative[8] = {0};
Acessing some wrong pointer in some place of your code will leads to 100% crash if its initiliazed to zero. Otherwise it will try to access some garbage value pointer which will leads to memory corruption, this sometimes will not crash instead will give unexpected output. But this also has a 50% chance of getting crash, which you are getting now.
scanf("%f", values[0]);
You need to pass the address of a location to store in to scanf(). It needs to be:
scanf("%f", &values[0]);
Otherwise, you're just telling scanf() to store the input value to whatever memory location is pointed at by the integer representation of the initialized value of values[0] -- which is most definitely not what you want.
The format for scanning a double is %lf; %f is for float. This is different from printf(), which confuses people — me too. You also need to pass a pointer to the variable.
If you use GCC, it should be warning you about a format mismatch. If it doesn't, you aren't compiling with enough warning options enabled (-Wall is a good start point; add -Wextra and -Werror if you can). The explicit option for checking printf() and scanf() formats is -Wformat, but it is included with -Wall.
#include <stdio.h>
int main(void)
{
double values[8];
printf("Enter first decimal number: ");
if (scanf("%lf", &values[0]) != 1)
printf("Scan failed!\n");
else
printf("values[0] = %g\n", values[0]);
return(0);
}
Note that this includes a newline at the end of the output, and also diagnoses when there is a problem (such as no data, or invalid data) on the input.
I thought an array was just a pointer to the first element of the array? Why do I have to use the ampersand?
An array is not just a pointer to the first element of the array, but when an array name is used in an expression other than as an argument of sizeof(), it changes to the pointer to the first element of the array.
You have to use the ampersand because values[0] is the value of the first element of the array, not the address of the first element of the array, and scanf() needs the address, not the value. Remember: a[i] == *(a + i) for an array name or pointer a and an index i, and note the * to dereference the pointer. If you wrote scanf("%lf", values) or scanf("%lf", values + 0), you are passing a pointer. Note that passing scanf("%lf", &values) would be a type mismatch (though the value passed as the address is the same — so it coincidentally 'works'). The type passed would be 'pointer to array of 8 double', which is not the same as 'pointer to double'.

Resources