I am currently studying C programming language and I was stuck because of "&", below is the sample code.
int main()
{
float degrees, radians;
printf("Enter an angle in degrees: ");
scanf("%f", °rees);
radians = 0.0174532925 * degrees;
printf("%.2f degrees is %.2f radians.\n", degrees, radians);
return(0);
}
Please take a look the bold and italic code. I want to know what is the use of "&". Because when I try to run the code that has no "&" in degrees it does run but when generating the answer it will hang-up.
Appreciate your immediate answer. Thank you!
The ampersand (&) is the C Address Operator; it returns the memory address of the given variable.
The scanf function reads data from the console, parses it, and stores the result in the memory address of the variable provided. The key to understanding the ampersand is that the scanf family of functions actually changes, in memory, the variable provided as an argument. Since we're working with the direct variable in memory and not a copy, we need to pass that variable's memory address -- hence the ampersand (&).
In your sample code the line scanf("%f", °rees) can be read as "Read a float ("%f") value into the memory address of degrees".
You can view the memory address being passed as an argument to scanf by adding the following line of code: printf("memory address of degrees: %p", °rees); before the return statement.
Have a look at the following for more details:
http://see-programming.blogspot.com/2013/10/difference-between-asterisk-and.html
http://beej.us/guide/bgc/output/html/multipage/scanf.html
scanf("%f", °rees);
Here scanf() stores value, so it needs a place to store them.
This is done by providing the addresses (in pointers) of
where to store the values. In your case it is degrees variable and by using °rees we are providing the address.
Hope this will help.
The & operator takes the address of the passed parameter and passes a pointer to it into the function, meaning that changing the value of the parameter in the function will also change it's value in the caller function.
You may think of the & as the "address" of the variable in the scanf statement. Essentially, the & is needed for primitive types in scanf statements; You don't see it being used in printf statement.
Take note that when you are using arrays in scanf statement, you will not need to use the & as the array name will provide an implicit &
Ampersand in C means the value is stored in this (variable)!
Related
While reading from a file in C, I was told that I can add an * after the % to disregard that input. For example:
fscanf(inputfile, "%lf %lf %*lf", &num1, &num2);
In this example the pointer reads three double values, but only two of them need to be stored (the ones without the * sign after the % sign).
Could someone explain how it works, because as far as I know the * sign is used to initialize or step into a pointer?
The use of * is just a string constant chosen arbitrarily. It has no relation to pointer dereferencing. How it "works" is that the parser in scanf simply parses the type as it would normally then throws away the value rather than looking for a parameter to put it in.
This question already has an answer here:
Program crashes when trying to read numbers with scanf
(1 answer)
Closed 8 years ago.
This program compiles fine. When I input a number, it crashes on me. name.exe has stopped working But why?
int main (void) {
int arrayMax = 0;
printf ("How many numbers will be entered?\n");
scanf ("%i", arrayMax);
int i;
double userInput [arrayMax];
return 0;
}
scanf ("%i", &arrayMax);
Do this scan to the address using &. You need to pass the address of the variable to which you need to scan the value to. In this case your variable is arrayMax and you need to pass the address of this variable which the scanf() expects and in this case you are not doing so and passing 0 which is not the memory location to which you want to scan your value to so you see crash.
Writing to in-valid memory location causes crash.
You forget to place & operator in the scanf argument.
scanf ("%i", &arrayMax);
// ^Place unary & to specify the location.
scanf is a variadic function.
As such, the compiler cannot determine whether or not the type of each argument passed to it is correct (expect for the type of the first argument, which is explicitly declared as const char*).
As a result, the decision is "moved" from compile-time to run-time, and so instead of a compile-time error you might get a run-time error.
For example, in the case of scanf("%i"), the function expects the address of an int variable.
In your code you are passing the value 0, so scanf will first scan user-input, and then attempt to write it at that memory address.
If the memory segment which includes this address does not have Write access permission (for example, if the code-section of your program resides at that address), then this attempt will result with a memory access violation during runtime.
You can get it to work correctly by changing scanf("%i",arrayMax) to scanf("%i",&arrayMax).
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);
Why do we pass the format specifiers to scanf( ) in C as its parameters?
I mean, can't we just do
scanf( &var ); // Here, var is any pre-declared variable.
the type of var can be fetched from its declaration. Why is this not allowed ?
I see the below code as a waste of memory.
scanf( "%d" , &var );
The type cannot be "fetched from it's declaration". There is nothing magical about scanf(), it's just a function. A function in C cannot access meta information about variables.
This is why, in general, function arguments are declared including their type. For variable-argument functions such as scanf(), the first argument is not optional and it is used to describe the number and type of the other arguments in some fashion chosen by the function itself.
You clearly need to read some book on C programming to get better understanding of the core concepts. Unlike some other languages, C doesn't have I/O mechanism baked into the language. scanf() is just a library function and as such, this function has no way to automagically know the type of the variable it is supposed to fill.
Because %d will simply specify what the type of var is, there is no memory wastage. scanf(&var) would not work because the function is not designed to accept arguments that way.
You know that variables in C can be of different types:
int: Integer
char: Character
float: Floating point number.
...
Unlike other languages, variable types cannot be implicitly inferred at compilation time in C. That is why you always declare the type of your variables ( Example: int a or char c).
Because scanf is just a function in C, and because functions in C should take parameters of a specific type, people who coded C decided to use the following format:
scanf("%d", &var) ; // for integers
scanf("%c", &var); //for chars
scanf("%f", &var); //for double and floats.
using %d or %c does not waste memory or whatsoever. you can think about it as a flag that specifies the type of the input variable.
Could the developers of C do it without %d, %c...etc? Yes they could, but then, they have to handle all possible exceptions that might arise from sending the wrong type.
Suppose the developers of C used just the following format
scanf(&var);
That is surly very concise, but then you will have to use the same syntax to send chars/int/double...etc, and then the function scanf has to figure out a way to decide about the type of the variable that was sent. Remember what I told you before? variable types CANNOT be implicitly inferred at compilation time, and thus, this task will be almost impossible.
They could however use a different scanf function for every type. For example:
scanfInt(&var); //for integers.
scanfFloat(&var); //for floats.
...
...
That would work perfectly, but it makes less sense to replicate the same code of scanf and use different functions just because the type is different.
So what is the solution? ==> Use the same function name ( scanf ), and then add a parameter (%d, %f, %c..) that will be used internally as a flag by C to know the parameter type.
I hope now you have a better understanding of the use of %d, %f....
There are two major points you are missing here.
First, we humans sitting at the keyboard will write something like:
char var = '0';
And we know that the "type" of this variable is char and we probably intend to store a character there. Once the compiler gets a hold of this it removes these "human" elements all that is left is at some memory location there is 1 byte reserved, further references to places in the code where we wrote "var" will interact with this memory location. That is all the compiler knows, there is no understanding of the intended variable "type".
Second, the format specificers do so much more than just indicate a simple type. Look at any page explaining scanf() and you'll see a long list, take special note of things like scan sets, negated scan sets, and expected input lengths.
Let's say I want the user to enter just a single digit, 0-9, well I don't have to just assume they will do as I ask, I can help ensure they will by using the format specifiers in scanf():
int var = 0;
print("enter 1 digit (0-9):\n");
scanf("%1d", &var);
Now, no matter how many digits they enter, I'll only have stored the first one.
What if you have a string that you want to read from the user, and you want to read everything up until you hit a new line character (read over spaces). We'll there are a number of options for this, but scanf can do it too. The "standard" to read a string is:
scanf("%s",some_string);
But that will stop at any whitespace character, so you wouldn't want scanf() to make an assumption in this case, you'd want to be able to use a specific negated scanset:
scanf("%[^\n]",some_string);
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'.