Dictate order that operands are evaluated in c - c

The statement puts("a") + puts("b") is undefined.
This is because it is not specified in the C Standard whether these ought to be executed left to right or right to left so you could get
a
b
or
b
a
Is there a clean way to dictate the order of operations in an expression?
The only thing I can think of is to use a compound statement such as
({
int temp = puts("a");
temp += puts("b");
temp;
})
though this is non-portable and a little longer than I was hoping.
How could this best be achieved?

If you declare an int variable before the expression, you can force order portably with the comma operator while computing the sum inside an expression:
int temp;
...
(temp = puts("a"), temp + puts("b"))
As specified in the C Standard:
6.5.17 Comma operator
Syntax
expression:
assignment-expression
expression , assignment-expression
Semantics
The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.
Note however that the value of the expression will not be very useful given the semantics of puts(), as commented by Jonathan Leffler.

The only way to force the order of evaluation is to use separate statements.
Compilers can use whatever order is deemed necessary. So for function calls f1() + f2() + f3(); any of one of those function calls could be called before the other. The only influence you can have on that statement is what to do with the returns from those functions. So in short, just use separate statements. Most likely for whatever you're doing, putting the calls in a loop should do fine.
Decent reference:
http://en.cppreference.com/w/c/language/eval_order

Related

In C, why expression(Statement) containing comma(,) operator work differently

I have a simple C code and big confusion about expressions containing comma(,) operator(s).
int main(){
int i=0,j=11,c;
c=i=j,++i;
printf("c=%d i=%d\n",c,i);
c=(i=j,++i);
printf("c=%d i=%d\n",c,i);
return 0;
}
The above code prints:
c=11 i=12
c=12 i=12
My questions are:
What is the actual work of comma(,) as an operator?
++ has more precedence than , and =, why evaluation is done for the expression on left of comma?
What will be the order if an expression contains operators with different priority, will it depend on comma(,)?
Is it behaving like a substitute of semicolon(;)?
The assignment operator has a higher priority then the comma operator.
Thus expression
c = i = j, ++i;
is equivalent to
( c = i = j ), ++i;
According to the C Standard (6.5.17 Comma operator)
2 The left operand of a comma operator is evaluated as a void
expression; there is a sequence point between its evaluation and that
of the right operand. Then the right operand is evaluated; the result
has its type and value.114)
In the expression above the result of the comma operator is discarded but it has a side effect of increasing i.
In this expression
c = ( i = j, ++i );
due to using parentheses you changed the order of the evaluation of the above expression. Now it is equivalent to
c = ( ( i = j ), ++i );
and variable c gets the value of expression ++i according to the quote from the C Standard listed above.
operator comma is to execute many statement and return only result of last statement.
So for c=i=j,++i; : c=i=j is executed, then ++i and after that result of ++i is returned (but not used).
And for c=(i=j,++i);, according to operator precedence, i=j is executed, and just after ++i is executed, and then affectation to c of result of (i=j, ++i), which is the result of last statement, i.e. ++i
So, the behavior of comma is not really same as semicolon. You can use it as a substitute like in c=i=j,++i;.
Personally, I do not encourage to use this operator, which generates less readable and less maintainable code
What is the actual work of comma(,) as an operator?
The comma operator is mainly a superfluous feature. See this for a description of how it works.
++ has more precedence than , and =, why evaluation is done for the expression on left of comma?
What will be the order if an expression contains operators with different priority, will it depend on comma(,)?
The left operand is evaluated for side effects. The result of the comma operator is the result of the evaluated right operand. Note that the comma operator has the lowest precedence of all operators in C.
Is it behaving like a substitute of semicolon(;)?
Kind of, yeah. Both a semi-colon and the comma operator includes a sequence point. The difference is that the comma operator isn't the end of a statement, so it can be squeezed in with other operators on the same line, and it also returns a result.
There is really no reason why you ever would want to do this though. The main use of the comma operator is to obfuscate code, it should be avoided. The only reason why you need to learn how it works, is because you might encounter crap code containing it.
For example, your nonsense code should be rewritten into something more readable and safe:
int main(){
int i=0;
int j=11;
int c;
i=j;
c=j;
i++;
printf("c=%d i=%d\n",c,i);
i=j;
i++;
c=i;
printf("c=%d i=%d\n",c,i);
return 0;
}
Well let's split it. In the first case c and i take the value of j => c=i=j=11; then you increment i => i=12; So the code is equivalent to this
c = j;
i = j;
++i;
For the second case i takes the value of j => i=j=11 and then you increment i => i=12 and then c takes the value of i => c = 12;
So the code is equivalent to this:
i = j;
++i;
c = i;
The comma operator will evaluate and discard all operations, up to, but not including, the final operation. This allows any number of non-consequential operations to be invoked together on a single line where only the last operation is of interest.
Think of it this way, if you have a number of loop variables to increment at any one location in a loop, you can separate all the additions/subtraction, etc.. over their own individual variables on separate line, but why? Where they are executed (within reason) is of no-consequence to the operation of the code. They then can be invoked on a single line with no adverse effect to the code.

C operator order

Why is the postfix increment operator (++) executed after the assignment (=) operator in the following example? According to the precedence/priority lists for operators ++ has higher priority than = and should therefore be executed first.
int a,b;
b = 2;
a = b++;
printf("%d\n",a);
will output a = 2.
PS: I know the difference between ++b and b++ in principle, but just looking at the operator priorities these precende list tells us something different, namely that ++ should be executed before =
++ is evaluated first. It is post-increment, meaning it evaluates to the value stored and then increments. Any operator on the right side of an assignment expression (except for the comma operator) is evaluated before the assignment itself.
It is. It's just that, conceptually at least, ++ happens after the entire expression a = b++ (which is an expression with value a) is evaluated.
Operator precedence and order of evaluation of operands are rather advanced topics in C, because there exists many operators that have their own special cases specified.
Postfix ++ is one such special case, specified by the standard in the following manner (6.5.2.4):
The value computation of the result is sequenced before the side
effect of updating the stored value of the operand.
It means that the compiler will translate the line a = b++; into something like this:
Read the value of b into a CPU register. ("value computation of the result")
Increase b. ("updating the stored value")
Store the CPU register value in a.
This is what makes postfix ++ different from prefix ++.
The increment operators do two things: add +1 to a number and return a value. The difference between post-increment and pre-increment is the order of these two steps. So the increment actually is executed first and the assignment later in any case.

Assigning multiple integers separated by comma to an int in C - Why does that work? What for? [duplicate]

This question already has answers here:
C comma operator
(4 answers)
What does the comma operator , do?
(8 answers)
Closed 7 years ago.
I saw this in an exam and when I tried it out I was surprised. I tried it online and it works too. So I think it is the C language.
Why is that working? What is the use case for such an assignment syntax?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int i = (1,2,3,4,5);
printf("%d", i);
return 0;
}
These are not "multiple integers", but a comma operator. The whole parenthesised part is a single expression with each sub-expression (separated by commas) evaluated strictly from left to right. The results of all but the rightmost subexpression are ignored. The result of the whole expression is that of the last (rightmost) expression. Here it is the integer value 5.
Note that this operator is mostly used where only a single expression is allowed to add further side-effects. E.g. in a loop like:
int cnt = 0;
for ( const char *cp = "Hello" ; *cp != '\0' ; cp++, cnt++ ) ;
This counts the number of characters in a C-string, incrementing the pointer and cnt after each iteration. The results are ignored here.
So, this is in no way related to tuples or similar like in Python. There are actually no cases the usage of this operator is unavoidable and it should be used with caution — and some coding standards forbid its usage.
That's the comma operator at work. It evaluates the expression on its left-hand side, creates a sequence point, discards the value of the expression, then evaluates the expression on the right-hand side, and returns that as the value. When there are multiple expressions as in the example, then each is evaluated in turn and only the last is kept. With the sample, the compiler does the evaluation because every value is known at compile time. Note that the argument list to a function is not a use of the comma operator.
That isn't a valid use-case for the comma operator. What might be a more nearly valid use-case would be some operations with side-effects (such as function calls) that need to be sequenced and the final value assigned:
int i = (getchar(), getchar(), getchar());
This sets i to the third character in standard input, or EOF if there are not three characters left in the standard input to be read. Still not a realistic use-case, but better than assigning a list of constants.
In addition to the other answers, you need to watch for instances where a , is the comma operator as opposed to when it is a separator. For example, the following is invalid:
int i = 1,2,3,4,5;
In this case, the , is a separator between variable declarations. It declares i as an int and initializes it to 1, then it attempts to parse 2 as a variable name, which fails.
It works because you're using the "comma operator", which evaluates the subexpressions on the left and right, and has the value from the right-hand expression.
So in (1,2,3,4,5), 1 is evaluated and the result is discarded, then 2,3,4,5... in which (because of the next comma) 2 is evaluated and the result discarded, then 3,4,5... in which 3 is evaluated and discarded, then 4,5... in which 4 is evaluated and discarded, then 5 which becomes the result of the expression.
As for when it's useful, mainly as a shortcut when you need to evaluate several (sub)expressions for their side effects but aren't interested in their values (except maybe the last one). It's sometimes convenient in for loop expressions, such as when incrementing two variables:
for (i=0,j=1; j < len; i++,j++) {
..where it appears in both the initialization expression and the loop expression.
Why is that working?
Because its a valid C syntax. The comma in (1,2,3,4,5) are comma operator
C11: 6.5.17 Comma operator
Syntax
1 expression:
assignment-expression
expression , assignment-expression
Semantics
2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.114)
What is the use case for such an assignment syntax?
See the example below
3 EXAMPLE As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second
expression of a conditional operator in such contexts. In the function call
f(a, (t=3, t+2), c)
the function has three arguments, the second of which has the value 5.

Why ternary operator does not support blocks?

Why the ternary operator does not have blocks? In other words, why the following code does not work and reports error for {} braces?
int main()
{
int i = 1;
(i==1)?{printf("Hello\n")}:{printf("World\n")};
return 0;
}
EDIT
Perhaps the question is misunderstood. It was: why blocks are not supported? Why only single expression?
Why this is not allowed to work?
int main()
{
int i = 1;
(i==1)?{printf("Hello\n");printf("World\n");}:{printf("Bye\n");printf("World\n");};
return 0;
}
One reason could be that ternary are often used for conditional assignment on left side and blocks will have no such returns or it will get confusing with multiple statements inside block.
To quote C11 standard, chapter §6.5.15, the syntax of the conditional operator is
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
Where, the second and third operands are expression, not statements.
Just to elaborate,
One of the following shall hold for the second and third operands:
— both operands have arithmetic type;
— both operands have the same structure or union type;
— both operands have void type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer and the other is a null pointer constant; or
— one operand is a pointer to an object type and the other is a pointer to a qualified or
unqualified version of void.
Edit:
To answer the question
Why only single expression?
again, quoting the standard,
....the result is the value of the second or third operand (whichever is evaluated), converted to the type described below.
Block of statements, will not give a value. The evaluation of an expression can.
The ternary operator consists of expressions. There is no such a kind of expression that uses braces.
You can write simply
( i == 1 ) ? printf("Hello\n") : printf("World\n");
It seems that the only case when braces can be present in an expression is the use of a compound literal. For example
struct A { int x; int y; } a = { 1, 2 };
a = a.x < a.y ? ( struct A ){ a.y, a.x } : ( struct A ){ ++a.x, --a.y };
As for this statement
(i==1)?{printf("Hello\n");printf("World\n");}:{printf("Bye\n");printf("World\n");};
then it can be rewritten the following way using the comma operator
i == 1 ? ( printf("Hello\n"), printf("World\n") ) : ( printf("Bye\n"), printf("World\n") );
Or even like
i == 1 ? printf("Hello\n"), printf("World\n") : ( printf("Bye\n"), printf("World\n") );
Shortly answering your question if you need a code block then use the if-else statement instead of the ternary operator. Though the if-else statement may not be used in expressions. On the other hand it is desirable for readability of the code that expressions would not be too compound.
As any operator the ternary operator is used in expressions and returns some evaluated value. For example as an expression it can be used as initializer or in assignments.
The ternary operator expects an expression for each part, and {...} is not an expression, but a statement.
To expand on your edit, the result of a ternary operator is an expression (but not an lvalue as you suggest), and statement blocks can't evaluate to a value.
For example, this doesn't make sense:
int x = (i==1)?{printf("Hello\n");printf("World\n");}:{printf("Bye\n");printf("World\n");};
But you could do this:
int x = (i==1)?(printf("Hello\n"), printf("World\n")):(printf("Bye\n"), printf("World\n"));
In which case, the comma operator would cause the last value in each subexpression to be returned.
Operators in C language can only be used in expressions. There's no such thing as "block" in an expression. In C language blocks are elements of higher-level syntactic structure. Blocks exists at the level of statements. Expression can be used in a statement. But statement cannot become an expression (or be used inside an expression).
Your particular example can be rewritten in terms of expressions
i == 1 ?
printf("Hello\n"), printf("World\n") :
printf("Bye\n"), printf("World\n");
without any need for {}.
(See Uses of C comma operator for extra information)
Yes only one expression is possible in ternary operators..You have to use if-else for multiple statements. Ternary operators takes one expression only in each slot
although you can call two different functions in ternary operator
#include <stdio.h>
void a(){
printf("Hello\n");
printf("Hi\n");
}
void b(){
printf("Hi\n");
printf("Hello\n");
}
int main()
{
int i = 1;
(i == 1) ? a() : b();
return 0;
}
The ternary operator is not meant to be used as a control structure, meaning it's not meant to control execution of statements. It's simply a way to choose which of two or more expressions will be evaluated.
As Sourav Ghosh has shown, the syntax of a conditional expression simply does not allow the operands of the ?: operator to be statements.
This is not allowed because it makes no sense. The ternary operator is meant to return a value. What would that be for {} blocks?
And then also there is another construct if () { } else { } that already serves the same purpose that you are trying to give to ? :. Doesn't this here look much nicer than the code that you posted?
int main(void)
{
int i = 1;
if (i==1) {
printf("Hello\n");
printf("World\n");
} else {
printf("Bye\n");
printf("World\n");
};
return 0;
}
As others have noted, GCC allows statements to be used syntactically as expressions, but such a feature is not part of the C standard. Historically, the reason for this likely had to do with the fact that statements are allowed to declare variables, and many systems use the same stack to hold local variables and parameters as is used to hold temporary values used in expression evaluation. Allowing new variables to come into existence within the execution of a statement while still keeping old variables in view would add some complexity to the compiler [note that when a function is called within a new expression, new variables are created for that function, but the old values will be "out of view" until the called function returns and the new variables are destroyed].
That having been said, other features of C such as variable-length arrays require far more complexity than would the ability to embed statements in expressions, so the arguments in favor of that design are no longer as compelling as they were in the 1970s. Unfortunately, the fact that something was once a compelling reason not to include a feature in a language may cause it to forevermore be perceived that way, even if design considerations for today's compilers are nothing like those of the 1970s.
Why ternary operator does not support blocks?
For roughly the same reason that a bicycle does not support wings.
If you have two blocks of statements, and you want to execute one or the other based on a condition, there's a perfectly good way to do that: the if/else statement.
And if you have two expressions, and you want to evaluate one or the other based on a condition, that's what the ternary or ?: operator is for.
But asking the ?: operator to execute one or the other of two blocks of statements is asking it to do something it's not meant for. Continuing the jokey analogies, it's like asking, why can't a hammer drive screws?
This distinction — that if/else is for blocks of statements, and ?: is for expressions — flows out of C's fundamental distinction between expressions and statements. They're only partially integrated in C: you can turn any expression into a statement by putting a semicolon after it, but you can not, in general, use a statement as an expression. Why not? Well, partly because the syntax of the language doesn't permit it, and partly because there's no universal definition of what the value of a statement (or a block of statements) is.
Now, you can certainly imagine a language in which every statement has a well-defined value. In such a language, if/else and ?: would probably be fully interchangeable. And, in fact, some C compilers do implement this full integration of expressions and statements, as an extension — but it's an extension, not Standard C.

setjmp remarks defined by standard

ISO/IEC 9899:1999
7.13.1.1 The setjmp macro
Environmental limits 4 An invocation of the setjmp macro shall appear
only in one of the following contexts: — the entire controlling
expression of a selection or iteration statement; — one operand of a
relational or equality operator with the other operand an integer
constant expression, with the resulting expression being the entire
controlling expression of a selection or iteration statement; — the
operand of a unary ! operator with the resulting expression being the
entire controlling expression of a selection or iteration statement;
or — the entire expression of an expression statement (possibly cast
to void).
So, the only variants of using setjmp are the following:
if (setjmp(buf))
while (setjmp(buf))
for (;; setjmp(buf))
if (setjmp(buf) == 0)
while (setjmp(buf) == 0)
for (;; setjmp(buf) == 0)
if (!setjmp(buf))
while (!setjmp(buf))
for (;; !setjmp(buf))
setjmp(buf);
(void)setjmp(buf);
And we can't use this statements:
int foo = setjmp(buf);
foo = setjmp(buf);
Right? What they mean by the iteration statement? The last statement of the for loop?
No you can't use
int foo = setjmp(buf);
foo = setjmp(buf);
The reason for the later (assignment) is probably that an assignment is an expression, that can have more than just an identifier on the left side. If the left side is an lvalue expression the standard imposes no order in which the subexpressions are evalutated. So if you have
int* f(void);
*f() = setjmp(buf);
*f() and setjmp(buf) could be evaluated in any order. Since setjmp makes a snapshot of the actual state of the abstract state machine, the semantics of boths orders would be completely different.
For the first line (initialization) this problem doesn't occur, I think. So I guess this could be added as a valid use. But it would have to be discussed carefully if there are no border cases that still require an evaluation on the left side.
(Eric already replied for the selection statements.)
Selection statements are if (including if…else) and switch. Iteration statements are while, do…while, and for.

Resources