Which argument in a function is called first? [duplicate] - c

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Why is the order of evaluation for function parameters unspecified in c++?
(2 answers)
Closed 3 years ago.
I cannot figure out the reason why I am getting this result. I am not the order in which the function calls it's arguments. I would assume that it would start at the first argument and go until the last. Here's the code...
#include <stdio.h>
int addmeup(int a, int b, int c){
printf("a:%d\n", a);
printf("b:%d\n", b);
printf("c:%d\n", c);
return a + 2 * b + 3 * c;
}
int main(){
int x = 1;
int y = addmeup(x++,x++,x++);
printf("x:%d\n", x);
printf("y:%d\n", y);
return 0;
}
I don't know why the result I am getting is...
a:3
b:2
c:1
x:4
y:10
For the function addmeup() why wouldn't the a be 1 instead of 3? Then b would be 2 and c would be 3. But it is the opposite. Can't seem to wrap my head around this.

In C and C++ the evaluation order of function arguments is undefined. It could be left to right, right to left, or randomized by running on multiple threads.
Also your example is even worse than that because function(x++, x++, x++) modifies x multiple times without a sequence point. Function argument commas are not sequence points. Which means x might be sent into the function call as x, x+1, x+2 or x+3. Since it is undefined it could even be 0 or call abort().

It is a undefined behaviour. It means anything can happen.
See GCC warning:
prog.c: In function 'main':
prog.c:15:30: warning: operation on 'x' may be undefined [-Wsequence-point]
15 | int y = addmeup(x++,x++,x++);
| ~^~
prog.c:15:30: warning: operation on 'x' may be undefined [-Wsequence-point]

Related

Is it possible to pass two arguments in c? [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 3 years ago.
I have written a C program where I declared a function reverse(int i). When I compile and run the program, it runs fine despite passing two arguments like this reverse((i++, i)). Why doesn't this cause a syntax error? reverse expects one argument.
#include <stdio.h>
void reverse(int i);
int main()
{
reverse(1);
}
void reverse(int i)
{
if (i > 5)
return ;
printf("%d ", i);
return reverse((i++, i));
}
You're not passing two arguments - that would be reverse(i++, i) (which incidentally would invoke undefined behaviour because of the lack of a sequence point between (i++ and i).
You're passing (i++, i) as a single argument. Since it is inside an additional pair of parentheses, the comma here does not separate the arguments of the function, but rather acts as the comma operator.
(i++, i) seems to execute i++, then evaluate to i, the last operand to ,. You can see that here:
// Notice the ( , )
int i = (puts("Inside\n"), 2); // Prints "Inside"
printf("%d\n", i); // Prints 2
It didn't cause an error because you only passed one argument. That one argument though was a sequence of effects that evaluated to i.

How to understand the behaviour of printf statement in C?

I have come across two C aptitude questions.
main()
{
int x=4,y,z;
y=--x;
z=x--;
printf("\n%d %d %d",x,y,z);
}
Output: 2 3 3 (it is printed left to right)
main()
{
int k=35;
printf("\n%d %d %d",k==35,k=50,k>40);
}
Output: 0 50 0 (it is printed right to left)
Why is it so? I have seen so many similar answers on Stack Overflow similar to this. People answer this is undefined behaviour, but if this is asked in interviews, how should one answer them?
The order of the evaluation of the arguments to any function in C is not in any particular order. It looks like the platform / compiler you are being asked about is probably evaluating the functions arguments right-to-left, which would print out the result you obtained, but the C standard says you do not know the order, so what is shown here is undefined behavior and would almost certainly obtain different results on a different compiler or platform.
Note, in your function, all the variable values are assigned before calling printf() - while in your main(), the values are being assigned to the variable in printf()'s argument list.
Yes, you need to read the documentation of printf. Read it carefully and several times.
You should compile with all warnings and debug info, i.e. using gcc -Wall -Wextra -g with GCC. Improve your code to get no warnings. Then use the gdb debugger to understand the behavior of your program.
On the second example (where I added the missing but mandatory #include <stdio.h>) GCC 8.1 gives on Linux/x86-64/Debian:
% gcc -Wall -Wextra -g m.c -o myprog
m.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main()
^~~~
m.c: In function ‘main’:
m.c:6:29: warning: operation on ‘k’ may be undefined [-Wsequence-point]
printf("\n%d %d %d",k==35,k=50,k>40);
~^~~
m.c:6:29: warning: operation on ‘k’ may be undefined [-Wsequence-point]
Also, as explained by John's H answer the order of evaluation of arguments is undefined (and the compiler gives some clue). A good way to think of it is to believe it is random and could dynamically change (but few implementations behave like that), and to write your source code in such way that won't change the intended behavior of your program.
In
printf("\n%d %d %d",k==35,k=50,k>40);
// ^
you have an assignment operator. So k is changing. But you don't know exactly when (it could happen after or before the k==35 and k>40 comparisons). So you have undefined behavior, be very scared!
At last, stdout is often buffered (see setvbuf(3) & stdio(3) for more) and usually line buffered. So the buffer could be flushed by the \n which you'll better place at the end of the format control string. Otherwise, ensure flushing by calling fflush(3).
From the C standard C99, section 6.5
The grouping of operators and operands is indicated by the syntax. 74)
Except as specified later (for the function-call () , && , || , ?:
,and comma operators), the order of e valuation of sube xpressions and
the order in which side ef fects tak ep lace are both unspecified.
So C standard doesn't say anything like that the function argument are solved from right to left & printed from left to right.
case 1 :- The statement y=--x; results in y=3 and x=3. when the expression z=x--; is performed. After this x=2 and z=3. Finally when the printf statement executed
printf("\n%d %d %d",x,y,z);
it prints 2 3 3.
Case 2 :- Here x=35 and when printf statement executes
printf("\n%d %d %d",k==35, k=50, k>40);
| | | <---- R to L (in your machine, seems argument passed from R to L, but can't grantee same for other platform)
50==35 50 35>40
| | | ----> L to R
0 50 0
In between, the main() prototype you used is incorrect. It should be int main(void) { /*... */ } as specified in C standard here
The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any
names may be used, as they are local to the function in which they are
declared):
int main(int argc, char *argv[]) { /* ... */ }
Let's trace through the code.
Example 1:
main()
This is no longer correct (since 1999). main needs a return type: int main().
{
int x=4,y,z;
Here x = 4 whereas y and z are indeterminate.
y=--x;
--x decrements x (from 4 to 3) and returns the new value of x (3), which is then assigned to y. At the end we have x = 3, y = 3, and z still indeterminate.
z=x--;
x-- decrements x (from 3 to 2) and returns the old value of x (3), which is then assigned to z. At the end we have x = 2, y = 3, z = 3.
printf("\n%d %d %d",x,y,z);
Here we're calling printf, but the function is not declared. The code is missing #include <stdio.h>; without it, the behavior is undefined (because it's calling an undeclared varargs function). But let's assume <stdio.h> was included. Then:
This outputs x, y, z as 2 3 3. Note that the format string should be "%d %d %d\n"; in the C model, lines are terminated by '\n', so you should always have a '\n' at the end.
}
Example 2:
main()
Same issue, should be int main() and #include <stdio.h> is missing.
{
int k=35;
Now k = 35.
printf("\n%d %d %d",k==35,k=50,k>40);
This is just broken. Function arguments can be evaluated in any order. In particular, the assignment to k (k = 50) and the comparisons (k == 35, k > 40) are not sequenced relative to each other, which means this piece of code has undefined behavior. You're not allowed to modify a variable while at the same time reading from it.
}
People answer this is undefined behaviour, but if this is asked in interviews, how should one answer them?
Tell them "this is undefined behavior". That's the correct answer. The example above is not required to produce any output. It could print 1 2 3, but it also could print hello!, or go into an infinite loop, or crash, or delete all of your files.
As far as the C standard is concerned, the code is simply meaningless.
(What happens on any particular platform is highly dependent on your compiler, the exact version of the compiler, any optimization options used, etc.)
I have seen so many similar answers on Stack Overflow similar to this.
People answer this is undefined behaviour,
And that's quite often the only correct answer.
but if this is asked in interviews, how should one answer them?
If your interviewer truly knows C, but chooses to ask this sort of question, it can be thought of as a trick question. They might seem to be expecting an answer like "1 50 1", but really they do expect the correct answer, which is, "It's undefined."
So if I were asked this question, I would give the interviewer a look suggesting "I can't believe you're asking me this", but then say, confidently, "It's undefined."
If the interviewer doesn't realize it's undefined, you have somewhat of a problem, but that's a human psychology and interview strategy question, not a C programming question, so I think I'll avoid delving into it further.

Does a change of value of a global variable by a function affect the order of addition? [duplicate]

This question already has answers here:
subexpressions evaluation order
(2 answers)
Closed 5 years ago.
I have tried the following code and got confused:
#include <stdio.h>
int m=3;
int f(void)
{
m--;
return m;
}
int main()
{
m=f()+m; //as + operator is executed from left to right, it is okay that m=2+2
printf("%d\n", m); //m=4, as expected
m=m+f(); //as + operator is executed from left to right, it should be like m=4+3
printf("%d\n", m); //but m=6
m+= f();
printf("%d\n", m);
return 0;
}
plus (+) operator is commutative, but here it seemed that the order of the summands matters!!! (according to the rule of associativity)
Why m is equal to 6 after the execution of m=m+f();?
It looks like the function call will always get preference!!!!
I am not sure whether it's an undefined behavior. m=m+m-- is an undefined behavior, as far as I know, but here the decrement task has been performed in an indirect manner- by a function.
In the question "subexpressions evaluation order", the answer was that "each of func1 and func2 can, if desired, interact with some shared data without having that data change under it in an unexpected way", but here the value of m has been changed by the function f.
I tried this code later and found another interesting thing. The function evaluation precedence is not the matter here- as this shows
#include <stdio.h>
int m;
int f()
{
m--;
return m;
}
int main()
{
m=4;
int x;
x=m+f()+f(); //if f() is evaluated first, then it should be like m=3+2+2
printf("%d\n",x); // but m=8
return 0;
}
m=m+f(); //as + operator is executed from left to right, it should be like m=4+3
printf("%d\n", m); //but m=6
This is correct because function call has highest precedence over + operator.
You can have a look at tbis
I hope this would help you.

C recursion code [duplicate]

This question already has answers here:
Implicit int return value of C function
(7 answers)
Closed 7 years ago.
I need help with understanding this code using recursion.
int power(int n1,int n2);
int main()
{
int base, exp;
printf("Enter base number: ");
scanf("%d",&base);
printf("Enter power number(positive integer): ");
scanf("%d",&exp);
printf("%d^%d = %d", base, exp, power(base, exp));
return 0;
}
int power(int base,int exp)
{
if ( exp!=1 )
return (base*power(base,exp-1));
}
The code works fine but I don't understand why it still manages to return a value when exp is 1 even when the condition in the function body evaluates to false, so I think it shouldn't return anything then.
For example, if the function is called in the main() function and I assign the values of 5 and 1 to base and exp respectively, I expect that I shouldn't get a return value because exp is 1 and my function returns something only if exp !=1 and also, there is no else part in the function body to cover the case when exp is 1.
I know about C returning garbage values when the return value is not specified but in this case, it returns the right answer and I tested it several times. For example, when I call it in the main function with base=7 and exp=1, it returns 7 as my answer and even with other "base" values, it always returns the base which is the right answer. And that exactly is my source of confusion - How is C managing to return the right answer to me when the IF clause of the function body evaluates to false...
I guess I'm missing something here.
Actually your function is Undefined Behaviour, because of is not returning nothing in case of exp == 1
The value you have in return to your main function is something random.
You may warned by the compiler in the declaration int power(int base,int exp)
No return, in function returning non-void
Hence, you will get undefined behavior, when you call power() with exp = 1.
Note that: Your power() will fall into recursion trap if exp is negative.
In your case, for exp having value 1, there is no return statement. If the return value of that call is used in the caller function, program shows UB.See note below
That said, the issue will also hold true in case you're calling power() with exp value something other than 1, as power() will end up calling itself with exp as 1 at some point of time.
Finally, exp being an int, it can accept a negative value and go into infinite loop, only to create stack overflow by infinite recursion.
Note: As per the C11 standard, if the function is terminated by reaching the closing } and the returned value is used, it invokes invokes undefined behaviour.
Ref: Chapter §6.9.1, paragraph 12,
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

What does a++ mean in C? [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
What is the difference between prefix and postfix operators?
(13 answers)
Closed 5 years ago.
I am trying to understand the basics of C programming and I'm kind of new to C, I am failing to understand why the output of my program is:
1 2
1 1
Quite alright, I understand the output from the first printf() but I do not seem to get the logic behind the second printf(). Why can't it display 1 2 as well?
#include <stdio.h>
int main()
{
int a = 1, b = 2;
printf("%d %d\n", a, b);
printf("%d %d\n", a, a++);
return 0;
}
a++ is post-incrementing a. That is, the value of a is copied before it is returned and then it is incremented.
As I mentioned in the comments, I get a different result to you, for the reason I explain below.
If you add printf("%d\n", a);, after your last call to printf() you'll see 2 because a has now been incremented.
If you want to see 1 2, you could pre-increment a (that is increment it and then use it), but you need to introduce a sequence point for this to be guaranteed to work because the order of evaluation of function arguments is unspecified by the standard and you want to use a twice:
printf("%d ", a);
printf("%d\n", ++a);
See it run!
The expression a++ evaluates to the current value of a and as a side effect increments a by 1. The expression ++a evaluates to the current value of a + 1 and as a side effect increments a by 1.
If you had written
a = 1;
printf("%d\n", a++);
you would get the output 1, because you're asking for the current value of a. Had you written
a = 1;
printf("%d\n", ++a);
you would get the output 2, because you're asking for the value of a + 1.
Now, what's important to remember (especially with ++a) is that the side effect of actually updating a doesn't have to happen immediately after the expression has been evaluated; it only has to happen before the next sequence point (which, in the case of a function call, is after all of the arguments have been evaluated).
Per the language definition, an object (such as the variable a) may have its value changed by the evaluation of an expression (a++ or ++a) at most once between sequence points, and the prior value shall be read only to determine the value to be stored.
The statement
printf("%d %d\n", a, a++);
violates the second part of that restriction, so the behavior of that statement is undefined. Your output could be any of 1 1, 1 2, a suffusion of yellow, etc.
Post Increment, increament after use
#include <stdio.h>
int main()
{
in a = 1, b = 2;
printf("%d %d\n", a, b); // 1 1
printf("%d %d\n", a, a++); // 1 1
printf("$d", a); // 2
return 0;
}
Following is pre-increment :
#include <stdio.h>
int main()
{
in a = 1, b = 2;
printf("%d %d\n", a, b); // 1 1
printf("%d %d\n", a, ++a); // Could Be "1 1" OR "1 2"... sequence is undefined here.
printf("$d", a); // 2
return 0;
}
Actually, ++x and x++ increment x the same way. The only difference is that ++x returns a reference to x and x++ returns the previous value as a temporary. The "incremented after it's been used" explanation is incorrect.

Resources