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.
Related
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Order of operations for pre-increment and post-increment in a function argument? [duplicate]
(4 answers)
function parameter evaluation order
(5 answers)
Closed 4 months ago.
I'm new to C and I'm writting some simple stuff to get familiar. I just tried pre-increment on an array index and what I got was really not what I was expecting.
The code in question:
#include <stdio.h>
int main()
{
int array[5] = {1,2,3,4,5};
int i = 0;
printf("%d %d",array[i], array[++i]);
return 0;
}
which should display elements of array[0] and array[1], right?
But it doesn't, as the output is 2 2
What am I missing?
Here's the thing: You can't guarantee what order function arguments are evaluated in.
What this means is, in your printf call, there's no way to tell whether array[i] or array[++i] will be evaluated first. In your case it appears that array[++i] won, so what happens is that you end up printing array[1] twice.
That's not a good use of pre-increment.
If you want to look at array[i] and array[i+1], just do that:
printf("%d %d\n", array[i], array[i+1]);
Remember, i++ does not just take i's old value and add 1 to it. It takes i's old value, and adds 1 to it, and stores the new value back into i. When you were printing array[i] and array[i+1], did you really want to change the value of i?
If you did want to change the value of i — or, in any case, since that mention of array[i++] did change the value of i — you introduced undefined behavior. Once you've got an expression that's modifying the value of i, how do you know what array[i] will print? How do you know that array[i] won't end up using the new value of i? You probably assumed that things are evaluated from left to right, but it turns out that's not necessarily true. So weird, weird things can happen.
Here's an example that helps show how ++ works, and that's well-defined:
#include <stdio.h>
int main()
{
int array[5] = {1,2,3,4,5};
int i = 1;
array[i++] = 22;
array[++i] = 44;
for(i = 0; i < 5; i++)
printf("%d: %d\n", i, array[i]);
return 0;
}
Or, as you suggested in a comment, if you did want to modify i's value, perhaps to advance the variable i along the array, you sometimes have to take care to move the i++ into a separate statement. The simple rule is, if you're applying ++ or -- to a variable, you can only use that variable once in the same statement. So you can't have i++ + i++, since that has two i's in it and they're both modified. But you also can't have i + i++, or f(a[i], a[i++]), since those have a spot where you modify i, and a spot where you use i, and there's no way to know whether you use the old or the new value of i. (And, again, in C there's not a general left-to-right rule that helps you here.)
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]
This question already has answers here:
What is the difference between ++i and i++?
(20 answers)
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 4 years ago.
I've recently started trying to learn C & was doing an exercise that involved creating a recursive factorial function.
Why does the following print out an answer of 24?
#include <stdio.h>
int factorial(int n);
int main(void)
{
int n = 5;
printf("%d\n", factorial(n));
return 0;
}
int factorial(int n)
{
if (n <= 1)
return 1;
else
return n * factorial(--n);
}
If i change the last line to
return n * factorial(n - 1);
I get the expected 120.
I understand that you can't use n-- b/c it only decreases n after the line is processed but whats wrong with --n & why does it give 24?
whats wrong with --n & why does it give 24?
The problem is that --n modifies n, so your line
return n * factorial(--n);
may evaluate like:
return (n - 1) * factorial(n - 1);
because the factorial(--n) is evaluated before the n that is the first term of the expression. On the other hand, the first term could be evaluated before the second, and you'd get the result you expect. Or, something entirely different could happen, because (as M.M and David C. Rankin point out in comments) what happens when you try to use a variable and modify it in the same expression is undefined:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
So let's address your title question:
Does (--n) equal (n - 1)?
The values of --n and of n - 1 are the same, but the former expression has the side effect that it modifies n. You should really think of --n as being shorthand for the expression (n = n - 1).
This question already has answers here:
Calling another function from printf?
(2 answers)
Closed 5 years ago.
printf("%d",func(i));
Is this possible in C?
Let us think that func(i) is separate function, can we call it inside printf or scanf?
Yes. Although it's rather special in some ways, printf is just another function. And a function call can be part of an expression. And the arguments you pass to functions are themselves expressions.
An expression is anything you can compute. So
i + 1
is an expression. But just plain
i
is also a (simpler) expression. And just plain
1
is an even simpler expression.
We build big expressions up out of littler ones. So if expr1 is an expression and expr2 is another expression, then
expr1 + expr2
is a bigger expression that combines them.
Just as you can take two little expressions (sometimes we call these "subexpressions") and combine them to form a larger expression using the + operator, we can also take some expressions and combine them together by calling a function:
f(expr1, expr2)
Now, returning to your question, the call
func(i)
is an expression. But when you call printf, what it expects to see for arguments is
printf(expression, expression, expression, ...)
Now, in printf's case, that first expression must be a string, and it's virtually always a constant string. But the remaining arguments can be anything: 1, i, i + 1, func(1), or just about anything:
printf("%d %d %d %d %d\n", 1, i, i+1, func(i), i+1+func(i));
The only thing to worry about, of course, is that you have as many expressions as additional arguments as you have % signs in the first argument (that is, in the format string), and the types of those additional arguments must match the types expected by the particular format specifiers you have used (%d, %f, %s, etc.).
#include<stdio.h>
int sum(int ,int );
void main()
{
int num1,num2;
printf("Enter two numbers: ");
scanf("%d %d",&num1,&num2);
printf("Sum of %d and %d is: %d",num1,num2,sum(num1,num2)); //function call in print statement
}
int sum(int num1,int num2) //function to add two numbers``
{
int result;
result=num1+num2;
return result;
}
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.