setjmp remarks defined by standard - c

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.

Related

Is the semicolon really a sequence point in C?

According to this answer, the following are the sequence points described in the standard:
Between the evaluations of the function designator and actual arguments in a function call and the actual call;
Between the evaluations of the first and second operands of the operators &&, ||, and ,;
Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated;
The end of a full declarator;
Between the evaluation of a full expression and the next full expression to be evaluated. The following are full expressions:
an initializer;
the expression in an expression statement;
the controlling expression of a selection statement (if or switch);
the controlling expression of a while or do statement;
each of the expressions of a for statement;
the expression in a return statement.
Immediately before a library function returns;
After the actions associated with each formatted input/output function conversion specifier;
Immediately before and immediately after each call to a comparison function, and also between any call to a comparison function and any movement of the objects passed as arguments to that call.
The standard never explicitly mentions that the semicolon is a sequence point, but the various sequence points that have been stated kind of imply that the semicolon is indeed a sequence point.
So, is the semicolon in break; or continue; a sequence point?
Is the semicolon really a sequence point in C?
No. Specific semantic language constructs are specifically required to have a sequence point after evaluating them. (like, ex. Logical AND operator ...if the second operand is evaluated, there is a sequence point between... - it's specific). A sequence point is indeed related to, like, semantics ("evaluation of this happens before that") rather than to tokens ("everything happens before the ; character").
So, is the semicolon in break; or continue; a sequence point?
No, it is not. Together with goto they look like a exception to the colloquial rule.
It is not a function call, not a logical operator && ||, not , operator, not a ternary ?: operator, not a declaration, not a full expression - it's not listed in the list you quoted (the list is from ANNEX C), it's not anyhow volatile and does no I/O. So, well, under the "when you have eliminated the impossible, whatever remains, however improbable, must be the truth" logic there is indeed no sequence point after break; nor continue;.
So, is the semicolon in break; or continue; a sequence point?
Better ask yourself, why shouldn't it not be a sequence point?
break and continue are just camouflaged goto, or "jmp".
goto always needs a label, aka a pointer, aka an argument, to be able to jump, same goes for break and continue (these get their label implicit by the surrounding loop).
...
Yes, the semicolon in break; or continue; is a sequence point.

In place vector "abs" warning: operation may be undefined? [duplicate]

A sequence point in imperative programming defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.
What does this mean? Can somebody please explain it in simple words?
When a sequence point occurs, it basically means that you are guaranteed that all previous operations are complete.
Changing a variable twice without an intervening sequence point is one example of undefined behaviour.
For example, i = i++; is undefined because there's no sequence point between the two changes to i.
Note that it's not just changing a variable twice that can cause a problem. It's actually a change involved with any other use. The standard uses the term "value computation and side effect" when discussing how things are sequenced. For example, in the expression a = i + i++, the i (value computation) and i++ (side effect) may be done in arbitrary order.
Wikipedia has a list of the sequence points in the C and C++ standards although the definitive list should always be taken from the ISO standard. From C11 appendix C (paraphrased):
The following are the sequence points described in the standard:
Between the evaluations of the function designator and actual arguments in a function call and the actual call;
Between the evaluations of the first and second operands of the operators &&, ||, and ,;
Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated;
The end of a full declarator;
Between the evaluation of a full expression and the next full expression to be evaluated. The following are full expressions:
an initializer;
the expression in an expression statement;
the controlling expression of a selection statement (if or switch);
the controlling expression of a while or do statement;
each of the expressions of a for statement;
the expression in a return statement.
Immediately before a library function returns;
After the actions associated with each formatted input/output function conversion specifier;
Immediately before and immediately after each call to a comparison function, and also between any call to a comparison function and any movement of the objects passed as arguments to that call.
An important thing to note about sequence points is that they are not global, but rather should be regarded as a set of local constraints. For example, in the statement
a = f1(x++) + f2(y++);
There is a sequence point between the evaluation of x++ and the call to f1, and another sequence point between the evaluation of y++ and the call to f2. There is, however, no guarantee as to whether x will be incremented before or after f2 is called, nor whether y will be incremented before or after x is called. If f1 changes y or f2 changes x, the results will be undefined (it would be legitimate for the compiler's generated code to e.g. read x and y, increment x, call f1, check y against the previously-read value, and--if it changed--go on a rampage seeking out and destroying all Barney videos and merchandise; I don't think any real compilers generate code that would actually do that, alas, but it would be permitted under the standard).
Expanding on paxdiablo's answer with an example.
Assume the statement
x = i++ * ++j;
There are three side effects: assigning the result of i * (j+1) to x, adding 1 to i, and adding 1 to j. The order in which the side effects are applied is unspecified; i and j may each be incremented immediately after being evaluated, or they may not be incremented until after both have been evaluated but before x has been assigned, or they may not be incremented until after x has been assigned.
The sequence point is the point where all side effects have been applied (x, i, and j have all been updated), regardless of the order in which they were applied.
It means a compiler may do funky optimizations, tricks and magic but must reach a well-defined state at these so-called sequence points.

Dictate order that operands are evaluated in 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

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.

is i=f(); defined when f modifies i?

Related question: Any good reason why assignment operator isn't a sequence point?
From the comp.lang.c FAQ I would infer that the program below is undefined. Strangely, it only mentions the call to f as a sequence point, between the computation of the arguments and the transfer of control to f. The transfer of control from f back to the calling expression is not listed as a sequence point.
int f(void) { i++; return 42; }
i = f();
Is it really undefined?
As an end-note that I add to many of my questions, I am interested in this in the context of static analysis. I am not writing this myself, I just want to know if I should warn about it in programs written by others.
The transfer of control from f back to
the calling expression is not listed
as a sequence point.
Yes it is.
at the end of the evaluation of a full expression
The complete expression that forms an
expression statement, or one of the
controlling expressions of an if,
switch, while, for, or do/while
statement, or the expression in an
initializer or a return statement.
You have a return statement, therefore, you have a sequence point.
It doesn't even appear that
int f(void) { return i++; } // sequence point here, so I guess we're good
i = f();
is undefined. (Which to me is kind of weird.)
That's not undefined at all. One of the sequence points listed in Appendix C of C99 is the end of a full expression, of which one is the expression in a return statement.
Since you're returning 42, there's a sequence point immediately following that return statement.
For completeness, the C99 sequence points are listed here, with the relevant one bolded:
The following are the sequence points described in 5.1.2.3:
The call to a function, after the arguments have been evaluated (6.5.2.2).
The end of the first operand of the following operators: logical AND && (6.5.13); logical OR || (6.5.14); conditional ? (6.5.15); comma , (6.5.17).
The end of a full declarator: declarators (6.7.5);
The end of a full expression: an initializer (6.7.8); the expression in an expression statement (6.8.3); the controlling expression of a selection statement (if or switch) (6.8.4); the controlling expression of a while or do statement (6.8.5); each of the expressions of a for statement (6.8.5.3); the expression in a return statement (6.8.6.4).
Immediately before a library function returns (7.1.4).
After the actions associated with each formatted input/output function conversion
specifier (7.19.6, 7.24.2).
Immediately before and immediately after each call to a comparison function, and
also between any call to a comparison function and any movement of the objects
passed as arguments to that call (7.20.5).

Resources