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'.
Related
For the purposes of an exercise, I was given a snippet of code and told to find the bug. I removed a bunch of noise and the part that is tripping me up is the following:
int main() {
char *p;
char n;
scanf("%i", n);
if (n < get_int()) {
p = malloc(n);
}
}
Here, if I enter a number for n, I get a seg fault. If I enter a character, n is set to 0. What is scanf doing that makes this so?
Edit: the exercise I'm trying to figure out is Exercise 2 from this page
It is simply UB.
C does not specify any specific behavior here. "%i" expect a int *, not an uninitialized char converted to an int.
"What is scanf doing that makes this so?" implies defined behavior. There is no specified UB.
"If I enter a character, n is set to 0. " --> scanf() does not attempt to change n, it uses a copy of n (passed by value).
The usual scanf() usages is like the below where the address of nn is passed, not nn itself.
int nn;
if (scanf("%i", &nn) == 1) Success();
else Failure();
You aren't just passing the wrong kind of variable to scanf, you are also passing it's value instead of the pointer to it. The scanf have no way of knowing this value isn't an actual pointer to store the scanned data into, so thats exactly what its going to try and do, scan the input and place it into whatever memory address the n, treated as pointer value, happened to point to. In the absolute most of the cases this will attempt to access unmapped/protected/etc memory, and cause segfault/access violation.
Entering a character simply terminates the scan prematurely, avoiding the segfault, and leaving the n intact. Bit since the value of n isn't initialized, it can happen to be just about anything, any junk that happened to be on the stack at that point of time.
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)!
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?
Hello Everyone I just want to clarify a doubt regarding pointers.So that I can know whether I understood it correctly or not.
void main ()
{
char c[10]="COMPUTERS";
printf("The first is %d\n",c); //1
printf("The second is %f\n",c); //2
printf("The third is %u\n",c); //3
printf("The fourth is %s\n",c); //4
printf("The fifth is %c\n",c); //5
}
The first printf will print the address of first location of character array 'c',
Similarly second printf will also try to print the address in float form.
The third printf will print the address again.
While the fourth printf will print the character array.
My doubt is associated with the 5th printf. It is printing random values or sometimes no values is it because the value of 'c' is memory address of first character of array 'c' and I am trying to print that value as a character?
all of those prints are undefined behavior except the %s one. the weird behavior you are seeing with %c format specifier is due to underlying casts on the adress of the pointer which can change from running it one time to the next.
if you want to print out the adress the pointer points to use %p like this:
printf("address: %p\n", (void *)c);
(These are not "doubts", they are questions or uncertainties perhaps).
All of those except %s are undefined behavior, since they all mis-match the actual type of the value provided (char *) with the formatting specifier.
printf("The fifth is %c\n",c[0]);
This makes sense. Printing the first character of the array.
Trying to print the address just as a character makes no sense.
Only this printf() is good
printf("The fourth is %s\n",c);
The rest of the printf()'s have undefined behavior.
The first printf will print the address of first location of character array 'c',
Strictly speaking, the first printf will invoke undefined behavior since you are using the wrong format specifier to print a pointer. But yeah it will probably print the address on most systems.
Similarly second printf will also try to print the address in float form.
No it will just give you some binary goo. You never convert the address to a float format, you only attempt to print it as if it was. This is completely undefined behavior.
The third printf will print the address again.
Same as 1. Undefined behavior, but yeah, it will probably print the address...
While the fourth printf will print the character array.
Yes.
My doubt is associated with the 5th printf. It is printing random values or sometimes no values is it because the value of 'c' is memory address of first character of array 'c' and I am trying to print that value as a character?
Again, undefined behavior. It can print anything.
Theoretical analysis:
printf("The first is %d\n",c); // undefined behavior by the standard
printf("The second is %f\n",c); // undefined behavior by the standard
printf("The third is %u\n",c); // undefined behavior by the standard
printf("The fifth is %c\n",c); // undefined behavior by the standard
Practical analysis:
printf("The first is %d\n",c); // requires sizeof(void*) == sizeof(int)
printf("The second is %f\n",c); // requires sizeof(void*) == sizeof(double)
printf("The third is %u\n",c); // requires sizeof(void*) == sizeof(unsigned int)
printf("The fifth is %c\n",c); // different between big-endian and little-endian
Detailed practical analysis:
sizeof(void*) < sizeof(...) will potentially yield a memory access violation during runtime
sizeof(void*) > sizeof(...) will yield different printout between big-endian and little-endian
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);