Pointer with float values, determine the output - c

What is the output of the following C program?
#include <stdio.h>
void abc (float, float, float *);
void main() {
float y = 2.5;
abc (6.5, y, &y);
printf ("%f\n",y);
}
void abc (float x, float y, float *z) {
y = y - 1;
*z = *z + x;
}
a) 1.5
b) 2.5
c) 8.0
d) 9.0
e) 9.5
The answer is d) 9.0. Could someone please explain why this is? I thought it would be c) 8.0 since in the function I updated the value of y as per y=y-1 to become 1.5. Thank you!

The short answer is that the y in main and the y in abc have the same name, but they are different. The one in abc is just a copy.
First, notice that the first line of the function abc is useless, it modifies y, but never uses y after that. Since when you call a function, a copy of each argument is made, this doesn't modify the y in main. And now the y in abc isn't used at all, so we can remove it from the parameters.
So you could rewrite abc as such :
void abc (float x, float *z) {
*z = *z + x;
}
And since there's not much point in such a simple one-line function, we can rewrite your program like this :
void main() {
float y = 2.5;
y = y + 6.5;
printf ("%f\n",y);
}
Now the result is pretty obvious.

abc (6.5, y, &y);
Please note that here the last parameter is call by reference and you are passing the address of the variable y.
Later in the function abc() you do
*z = *z + x
*z = 2.5 which is called dereferencing the pointer and the value stored in the address the pointer is pointing to is 2.5 and x=6.5 as you are passing it by value.So
*z = 2.5 + 6.5 = 9.0
Now in main() the value of y=9.0 because the value stored in the address of the variable y was modified by the function call abc()

When calling abc (6.5, y, &y) inside the function it will look like this:
void abc (x = 6.5, y = 2.5, *z = 2.5) {
y = 2.5 - 1; // y = 1.5
*z = 2.5 + 6.5; // *z = 9.0
}
And *z inside the function is same as y outside the function, so y = 9.0.

Simple, the third argument is a pointer to y in main(). That y value is being printed later on.
inside abc(), float y is local variable. any changes made to its value is not reflected back in the caller parameter.
OTOH, as per the logic of pointers, *z retains the computed value inside abc() thereby reflecting back the value to main().
In short, the computed value inside abc() is reflected back using the third argument z.
Calculation for z ==> 6.5 + 2.5 = 9.0

Related

C sqrt not working properly on floating point numbers below 1 but above 0

I am trying to create a vector with random dimensions, but with a magnitude of 1. This is what I've come up with (removed the rand() function and replaced it with a number common to both pieces of code.):
float x = sqrt((4566%100)/100.f);
float y = sqrt(1.f-x);
printf("%f, %f\n", x, y);
printf("%f\n", (x*x)+(y*y));
The output is this:
0.812404, 0.433124
0.847596
but when I remove the inverse of the pythagorean theorum (with the code looking a little something like this):
float x = (4566%100)/100.f;
float y = 1.f-x;
printf("%f, %f\n", x, y);
printf("%f\n", x+y);
the output looks like this:
0.660000, 0.340000
1.000000
Based on the assumption that I'm not insane, the output of the last line of the first piece of code should be 1, and the vector being printed above should be something completely different. I can only assume that the thing that has gone wrong is in the sqrt function. If it is, could someone help me fix it and if it isn't, could someone help me identify my error?
If, according to the Pythagorean theorem, sqrt(x * x + y * y) = 1, then y is not equal to sqrt(1.f-x). It should be sqrt(1.f-x*x):
sqrt(x * x + y * y) = 1
(square both sides) => x * x + y * y = 1
(subtract x * x from both sides) => y * y = 1 - x * x
(calculate the square root of both sides) => y = sqrt(1 - x * x)
Given the computation for x, this computation of y is incorrect:
float y = sqrt(1.f-x);
You need to subtract the square of x:
float y = sqrt(1.f-x*x);
Since x is between 0 and 1, x2 < x, and that will yield a larger (and correct, modulo FP error) value of y.

C multiple variable assignment

I'm first year student in Software Engineering and in my last task I used (chain assignment) multiple assignment of values.
The lecturer claims that it is illegal to assign values in this way.
X = Y = Z;
(The three variables are declared in the beginning of the function).
I would be happy if you can explain to me if the assign is right action and if what the teacher claims is right.
It depends on whether all of the objects were correctly declared and Z was initialized or assigned with an appropriate value before this statement or not.
You can even assign values of objects of different types due to implicit casting, but the object which is getting assigned needs to be capable of holding the value of the object which is assigned to this one.
If Z was initialized or assigned before and all objects were correct declared, then:
X = Y = Z;
is completely correct and legal as it assigns the value held in Z to Y and X - the assignment takes place from right to left.
For example:
int X,Y,Z; // All objects are declared.
Z = 24; // `Z` is assigned with the integer value 24.
X = Y = Z; // `X` and `Y` get assigned by 24 which is the value in `Z`.
Else if Z has an indeterminate value (f.e. if it was not declared with the extern or static keyword or declared at global scope) and you would assign this value to Y and X with that statement.
Although the assignment itself would be even then not illegal, if you would use one of the assigned objects the program would give undefined results/output.
Speaking for the multiple assignments only, there is nothing illegal about it, you could even use:
O = P = Q = R = S = T = U = V = W = X = Y = Z;
if all objects used were correctly declared before and Z has an determined value.
The lecturer claims that it is illegal to assign values in this way.
If it is possible, I would ask her/him or your teacher, what s/he meant with that. Maybe there is something specific to your course you should care about.
Almost every expression has a value.
An assignment is an expression with value.
The value of the expression i = 42 is 42.
Assignment associates right to left, so the expression a = b = c is the same as a = (b = c).
So
int i;
double d;
char c;
c = i = d = 42;
Converts 42 to double and assigns to d. The value of this assignment is 42.0.
Then this value is converted to int and assigned to i. Value of this assignment is 42.
Lastly the int value is converted to char and assigned to c.
c = (i = (d = 42));
It's legal, for example:
float x;
int y;
float z = 3.5;
x = y = z;
it's similar to y = z; x = y;. So in this case, z = 3.5, y = 3 and x = 3;
But it will give the warning if you did not initialize the value of z.
int x,y, z;
x = 0;
y = 1;
//z = 2;
x = y = z;
Together with right-associativity of evaluation, and assuming non-volatile a, b, and c, it means that a = b = c is equivalent to a = (b = c), and again equivalent to b = c; a = b
Assigning values to multiple variables in a single line is perfectly alright and is allowed by C programming language.
However, the use of this style is usually discouraged because it may cause undesirable side-effects in some cases.
The expectation of Mathematical equation X = Y = Z may be:
Y = Z and X = Z (I.E., Assign the value of Z to both X and Y)
But C language treats the multiple assignments like a chain, like this:
In C, "X = Y = Z" means that the value of Z must be first assigned to Y, and then the value of Y must be assigned to X.
Here is a sample program to see how the multiple assignments in single line work:
#include <stdio.h>
int main() {
int n;
int X, Y, Z;
printf("Enter an integer: ");
scanf("%d", &n);
printf("You entered: %d\n", n);
printf("Performing multiple assignments:\n X = Y = Z = n++ \n");
X = Y = Z = n++;
printf("n = %d\n", n);
printf("X = %d \n", X);
printf("Y = %d \n", Y);
printf("Z = %d \n", Z);
return 0;
}
Output:
Enter an integer: 100
You entered: 100
Performing multiple assignments:
X = Y = Z = n++
n = 101
X = 100
Y = 100
Z = 100
Points to note in the above example:
The line X = Y = Z = n++ got processed like this:
Step 1: Assign the value of n (100) to Z
Step 2: Increment the value of n (n becomes 101)
Step 3: Assign the value of Z to Y (Y becomes 100)
Step 4: Assign the value of Y to X (X becomes 100)
Conclusion:
'Multiple assignments in single line' is a supported style. It has its benefits.
However, if the programmer is not aware of the sequence of operations involved in the multiple assignments statement, then it can lead to inconsistency between the expectation of the person who reads the program and the actual result of the execution.
To avoid this scenario, the multiple assignments are discouraged.
There's nothing illegal about it, provided each variable is only modified once. For example, the following all have well-defined behavior:
x = y = z;
x = y = z = x + 1;
x = y++ + --z;
x += (y = (z += 1)) - 6;
But the following have undefined behavior, and should be avoided:
x = y = x = z;
x = x++;
x = y++ + y++
x = func(y++, y++);

Which statement will change value of x to 60 in C programing?

int *p;
int x;
int k;
x = 30;
k = x;
p = &x;
After these statements, which of the following statements will the value of x to 60? My answer is 1. But I'm not sure if I am correct, because seem like other answer is correct too. Please gives some explanation.
1. k = 60;
2. *k = 60;
3. p = 60;
4. *p = 60;
Here is an explanation:
int *p; //declares a pointer to an integer
int x; //declares an integer called x
int k; //declares an integer called k
//at this point all values are uninitialized and could contain anything
x = 30; //the numerical value 30 is assigned to x
k = x; //the contents of x(30) is assigned to k
p = &x; //the address of int x is stored in p
//now all values have valid and reliable values
Now let me explain what each line you described does:
k = 60; //assigns value 60 to variable k
*k = 60; //attempts to dereference k which is a non pointer type (compile time error)
p = 60; //attempts to assign the value 60 to a pointer p this is NOT what you want
*p = 60; //dereferences pointer p(which points to x) and sets the value 60 to it
the last line has the same effect as x=60; so it is the correct answer.
k=60; will not affect the content of x, because x and k are different variables they each have their own separate memory. k=x; will simply copy the contents of x into k, it will not make the variables aliases of each other.
You can simply compile it and run it in a debugger via single step to see how it works.
The answer is not 1. You're close, answers 2 and 3 don't make sense.
p = &x
p points to the memory address of x so setting
p = 60
would be setting its address to 60 which is not what you want.
k = x;
Changing k will not change x because k doesn't store the memory of x, it has instead copied the value of x.
*p = 60
The value that p is pointing to equals 60, in this case p is pointing to the address of x
So when ever the value at the address of x changes, *p changes or vice versa.
The key point is *p is pointing the value at the memory address of x, so changing *p changes x
The answer is 4.

Double turns into nan in C

I have a function that uses an int, say 2488, to store temperature values. I have to call a function getTemp() to get the int. The getTemp function returns a double and uses the int to return the correct number. All the getTemp() does is return (double)x / 100.0 where x is 2488 in this case.
The returned double is then 24.88. This value then is sent to another function that adds the double to an array. Function is called DAaddDouble(double m, int x, int y) where m is the value to add, x and y is the coordinates that specify where to add the double.
Problem is, it turns into nan.
double a = getTemp();
//a is correct, i.e. 24.88
DAaddDouble(a, x, y);
/*-----------inside DAaddDouble----------*/
void DAaddDouble(double m, int x, int y)
{
//at this point, a (or m, same) is 0.nan
cord = x + y*40; //where to put the double
snprintf(DARRAY[cord], 5, "%f",m);
printf(....DARRAY[cord]...);
}
output: -nan
The signature of function DAaddDouble is:
void DAaddDouble(int m, int x, int y)
Note that m is of type int, and inside the function, you have:
snprintf(DARRAY[cord], 5, "%f",m);
in which %f expects type double, it's undefined behavior.
Probably what you need is to have the parameter m as double(as in your words above the code).
void DAaddDouble(double m, int x, int y)
Mis-match prototype.
Usage of DAaddDouble() is not preceded by its declaration/definition, thus the compiler assumes the function is:
int DAaddDouble(int m, int x, int y);
Precede the usage of DAaddDouble() by the function definition or a function prototype.
void DAaddDouble(double m, int x, int y);
A good compiler will warn of this. Insure all warning are enabled.
How do you know m is NAN. If you have infered by the value "printed" to DARRAY[cord], take into account that the format string should be "%lf" and not "%f".
void DAaddDouble(double m, int x, int y)
{
//at this point, a (or m, same) is 0.nan
cord = x + y*40; //where to put the double
snprintf(DARRAY[cord], 5, "%f",m); /* should be "%lf" for printing doubles */
printf(....DARRAY[cord]...);
}

difference between *y++ and ++*y?

I'm confused in how this code will get executed. Suppose we have
int x=30,*y,*z;
y=&x;
what is the difference between *y++ and ++*y? and also what will be the output of this program?
#include<stdio.h>
int main(){
int x=30,*y,*z;
y=&x;
z=y;
*y++=*z++;
x++;
printf("%d %d %d ",x,y,z);
return 0;
}
The expression x = *y++ is in effects same as:
x = *y;
y = y + 1;
And if expression is just *y++; (without assignment) then its nothing but same as y++;, that is y start pointing to next location after increment.
Second expression ++*y means to increment the value pointed by y that same as: *y = *y + 1; (pointer not incremented)
It will be better clear with answer to your first question:
Suppose your code is:
int x = 30, *y;
int temp;
y = &x;
temp = *y++; //this is same as: temp = *y; y = y + 1;
First *y will be assigned to temp variable; hence temp assigned 30, then value of y increments by one and it start point to next location after location of x (where really no variable is present).
Next case: Suppose your code is:
int x = 30, *y;
int temp;
y = &x;
temp = ++*y; //this is same as *y = *y + 1; temp = *y;
First value of *y increments from 30 to 31 and then 31 is assigned to temp (note: x is now 31).
next part of your question (read comments):
int x = 30, *y, *z;
y = &x; // y ---> x , y points to x
z = y; // z ---> x , z points to x
*y++ = *z++; // *y = *z, y++, z++ , that is
// x = x, y++, z++
x++; // increment x to 31
what is the difference between *y++ and ++*y?
The meaning of an expression in C is characterized by two things: what value it produces and what side effects it produces.
Let's examine the first expression.
Postfix increment is of higher priority than dereferencing, so this is *(y++).
The postfix increment produces a side effect: it changes the value of y to point to a different location. The postfix increment also produces a value: the value that y had before it was incremented. The * operator then dereferences that value to produce an lvalue: that is, something you can use as a variable, either to store to or to fetch from.
I note that the side effect can happen at any point before or after the dereferencing. If you said
q = *y++
then the side effect of the ++ could happen at any point. This could be:
q = *y;
y = y + 1;
or it could be treated as
t = y;
y = y + 1;
q = *t;
Both are perfectly legal. (Except of course that if y is itself an expression with side effects, those side effects must be produced only once. For clarity, I'll make that assumption throughout.)
How about ++*y? That is straightforward: *y produces a variable, the content of the variable is incremented, and the value of the expression is the incremented value. Note that again, the side effect can be produced out-of-order:
q = ++*y
could be treated as:
t = *y + 1;
*y = t;
q = t;
or as
t = *y + 1;
q = t;
*y = t;
Remember, C does not produce very many restrictions on the order in which side effects may happen, so be careful.
what is the difference between *y++ and ++*y?
In case of expression *y++ and *z++; because the postfix version ++ takes precedence over *, the compiler sees this as;
*(y++) = *(z++);
In case of ++*y; compiler sees this as ++(*p) and it will first increment the value of the object it points to ( x in this case) and then return its incremented value.
Summary table for other possibilities;
Expression Meaning
-------------------------------------------------------------------------------------
*y++ or *(y++) Value of expression is *y before increment; increment y latter
(*y)++ Value of expression is *y before increment; increment *t later
*++y or *(++y) Increment y first; value of expression is *y after increment
++*y or ++(*y) Increment *y first; value of expression is *y after increment
EDIT: As pointed out by Eric Lippert in his comment that saying: value of expression is *y before increment, increment y later is misleading, I want to clarify here that the words I used latter and after to emphasize that previous or next value of *y, respectively, will be used in expressions.
Note that, the side-effect can be produced in any order, either side-effect produce first and value assigned latter or value assigned first and side-effect produce latter. For more detail read the answers :-- 1, 2 given by Eric Lippert.
I trust that you understand what the operators ++ and * means when used separately. When used together then operator precedence comes into play. In C++ the ++ operator has a higher precedence than the * operator. So effectively *y++ means *(y++) and ++y* means (++y)*. I hope this helps.

Resources