variable 1 = ({statement 1;statement 2;}) construct in C - c

main()
{
int a=10,b=30,c=0;
if( c =({a+b;b-a;}))
{
printf("%d",c);
}
}
why the construct ({;}) is legal in C and why it returns the last statement value as the result of the expression ( why it work similar to comma operator)?

It is not legal standard C99, but it is a very useful GCC extension, called statement-exprs (a parenthesized brace compound statement ending by some expression).
IIRC, some other compilers support that extension, e.g. Clang/LLVM
Statement expressions are much more useful when they contain control flow changes and side-effects, like:
c = 2*({while (a>0) a--,b--; a+b;});
However, in your particular case, you could just use the comma operator
if (c=(a+b,b-a))
Since a+b does not have any side effect, I guess that an optimizing compiler could handle that as
if (c=b-a)
GCC provides other useful extensions, notably local labels using __label__ and label as values with computed gotos (very useful in threaded interpreters ...). I don't know exactly why they have not been standardized. I wish that they would.

main()
{
int a=10,b=30,c=0;
if( c =({a+b;b-a;}))
{
printf("%d",c);
}
}
Here,{a+b;b-a;} is one scope.In this you have written 2 statements.This is actually treated as
{
c=a+b;
c=b-a;
}
Initially c value is 40 because of a+b. Again c is modified by b-a. To prove this consider following three cases..
(1).
if(c=({(a=a+b);;}))
{
printf("%d\n",c);
printf("%d\n",a);
}
Here o/p is c=40 and a=40;Because at end of scope (i.e) in last statement is dummy (;).
so,c=a+b is o/p.
(2)
if(c=({(a=a+b);b-a;}))
{
printf("%d\n",c);
printf("%d\n",a);
}
Here o/p is c=-10, a=40. Because last statement is b-a. this value is assigned to c.
(3) main()
{
int a=10,b=30,c=0;
if(c=({(a=a+b);0;}))
{
printf("%d\n",c);
printf("%d\n",a);
}
printf("%d\n",c);
}
Here o/p is c=0 only.If is not executed ,Because of last statement is 0;
C follows procedure oriented.And associativity of () is left to right.

Related

Why are statements with no effect considered legal in C?

Pardon if this question is naive. Consider the following program:
#include <stdio.h>
int main() {
int i = 1;
i = i + 2;
5;
i;
printf("i: %d\n", i);
}
In the above example, the statements 5; and i; seem totally superfluous, yet the code compiles without warnings or errors by default (however, gcc does throw a warning: statement with no effect [-Wunused-value] warning when ran with -Wall). They have no effect on the rest of the program, so why are they considered valid statements in the first place? Does the compiler simply ignore them? Are there any benefits to allowing such statements?
One benefit to allowing such statements is from code that's created by macros or other programs, rather than being written by humans.
As an example, imagine a function int do_stuff(void) that is supposed to return 0 on success or -1 on failure. It could be that support for "stuff" is optional, and so you could have a header file that does
#if STUFF_SUPPORTED
#define do_stuff() really_do_stuff()
#else
#define do_stuff() (-1)
#endif
Now imagine some code that wants to do stuff if possible, but may or may not really care whether it succeeds or fails:
void func1(void) {
if (do_stuff() == -1) {
printf("stuff did not work\n");
}
}
void func2(void) {
do_stuff(); // don't care if it works or not
more_stuff();
}
When STUFF_SUPPORTED is 0, the preprocessor will expand the call in func2 to a statement that just reads
(-1);
and so the compiler pass will see just the sort of "superfluous" statement that seems to bother you. Yet what else can one do? If you #define do_stuff() // nothing, then the code in func1 will break. (And you'll still have an empty statement in func2 that just reads ;, which is perhaps even more superfluous.) On the other hand, if you have to actually define a do_stuff() function that returns -1, you may incur the cost of a function call for no good reason.
Simple Statements in C are terminated by semicolon.
Simple Statements in C are expressions. An expression is a combination of variables, constants and operators. Every expression results in some value of a certain type that can be assigned to a variable.
Having said that some "smart compilers" might discard 5; and i; statements.
Statements with no effect are permitted because it would be more difficult to ban them than to permit them. This was more relevant when C was first designed and compilers were smaller and simpler.
An expression statement consists of an expression followed by a semicolon. Its behavior is to evaluate the expression and discard the result (if any). Normally the purpose is that the evaluation of the expression has side effects, but it's not always easy or even possible to determine whether a given expression has side effects.
For example, a function call is an expression, so a function call followed by a semicolon is a statement. Does this statement have any side effects?
some_function();
It's impossible to tell without seeing the implementation of some_function.
How about this?
obj;
Probably not -- but if obj is defined as volatile, then it does.
Permitting any expression to be made into an expression-statement by adding a semicolon makes the language definition simpler. Requiring the expression to have side effects would add complexity to the language definition and to the compiler. C is built on a consistent set of rules (function calls are expressions, assignments are expressions, an expression followed by a semicolon is a statement) and lets programmers do what they want without preventing them from doing things that may or may not make sense.
The statements you listed with no effect are examples of an expression statement, whose syntax is given in section 6.8.3p1 of the C standard as follows:
expression-statement:
expressionopt ;
All of section 6.5 is dedicated to the definition of an expression, but loosely speaking an expression consists of constants and identifiers linked with operators. Notably, an expression may or may not contain an assignment operator and it may or may not contain a function call.
So any expression followed by a semicolon qualifies as an expression statement. In fact, each of these lines from your code is an example of an expression statement:
i = i + 2;
5;
i;
printf("i: %d\n", i);
Some operators contain side effects such as the set of assignment operators and the pre/post increment/decrement operators, and the function call operator () may have a side effect depending on what the function in question does. There is no requirement however that one of the operators must have a side effect.
Here's another example:
atoi("1");
This is calling a function and discarding the result, just like the call printf in your example but the unlike printf the function call itself does not have a side effect.
Sometimes such a statements are very handy:
int foo(int x, int y, int z)
{
(void)y; //prevents warning
(void)z;
return x*x;
}
Or when reference manual tells us to just read the registers to archive something - for example to clear or set some flag (very common situation in the uC world)
#define SREG ((volatile uint32_t *)0x4000000)
#define DREG ((volatile uint32_t *)0x4004000)
void readSREG(void)
{
*SREG; //we read it here
*DREG; // and here
}
https://godbolt.org/z/6wjh_5

Function returns correct value when i use conditional operator or if statement without return statement

#include<stdio.h>
int fact(int);
int main()
{
int a, b;
printf("enter a number : ");
scanf("%d",&a);
b=fact(a);
printf("\n%d",b);
}
int fact(int y )
{
int d=1;
for(int i = 1;i<=y;i++)
d*=i;
d= d>0 ? d : 0;
}
If I remove the last statement , O/P is a+1.
I have checked this with other functions and the function returns correct values if I use if statement or conditional operator.
I want to know why this happens.
Thank You.
6.9.1 Function definitions
...
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.
Simply put, the behavior you're seeing is purely accidental. There's no good reason why you should get that particular result or any other.
Undefined means that the code is erroneous, but neither the compiler nor the runtime environment are required to handle it in any particular way. What's likely happening in your case is that the register used to return a value from a function is also being used to store the value of d, but that doesn't have to be true. If you change up the code, you may get a different result.

Call by Need and Standard C Output?

The following code is here with keep the C Language Syntax:
#include <stdio.h>
int func(int a, int b){
if (b==0)
return 0;
else return func(a,b);
}
int main(){
printf("%d \n", func(func(1,1),func(0,0)));
return 0;
}
What is the output of this code at 1) run with standard C, 2) with any
language that has call by need property, Then:
in (1) the programs loop into infinite call and in (2) we have ouptut zero !! this is an example solved by TA in programming language course, any idea to
describe it for me? thanks
1) In C (which uses strict evaluation semantics) we get infinite recursion because in strict evaluation arguments are evaluated before a function is called. So in f(f(1,1), f(0,0)) f(1,1) and f(0,0) are evaluated before the outer f (which one of the two arguments is evaluated first is unspecified in C, but that does not matter). And since f(1,1) causes infinite recursion, we get infinite recursion.
2) In a language using non-strict evaluation (be it call-by-name or call-by-need) arguments are substituted into the function body unevaluated and are only evaluated when and if they're needed. So the outer call to f is evaluated first as such:
if (f(0, 0) == 0)
return 0;
else return f(f(1,1), f(0,0));
So when evaluating the if, we need to evaluate f(0,0), which simply evaluates to 0. So we go into the then-branch of the if and never execute the else-branch. Since all calls to f are only used in the else-branch, they're never needed and thus never evaluated. So there's no recursion, infinite or otherwise, and we just get 0.
With C, in general, it is not defined the order of arguments a and b evaluation with a function like int func(int a, int b)
Obviously evaluating func(1,1) is problematic and the code suffers from that regardless if func(1,1) is evaluated before/after/simultaneous with func(0,0)
Analysis of func(a,b) based on need may conclude that if b==0, no need to call func() and then replace with 0.
printf("%d \n", func(func(1,1),func(0,0)));
// functionally then becomes
printf("%d \n", func(func(1,1),0));
Applied again and
// functionally then becomes
printf("%d \n", 0);
Of course this conclusion is not certain as the analysis of b != 0 and else return func(a,b); leads to infinite recursion. Such code may have a useful desired side-effect (e.g. stack-overflow and system reset.) So the analysis may need to be conservative and not assume func(1,1) will ever return and not optimize out the call even if it optimized out the func(0,0) call.
To address the first part,
The C Draft, 6.5.2.2->10(Function calls) says
The order of evaluation of ... the actual arguments... is unspecified.
and for such reason, something such as
printf("%d%d",i++,++i);
has undefined behaviour, because
both ++i and i++ has side-effects, ie incrementing the value of i by one.
The comma inside printf is just a separator and NOT a [ sequence point ].
Even though function call itself is a sequence point, for the above reason, the order in which two modifications of i take place is not defined.
In your case
func(func(1,1),func(0,0))
though, the arguments for outer func ie func(1,1) or func(0,0) have no bearing on each other contrary to the case shown above. Any order of evaluation of these arguments eventually leads to infinite recursion and so the program crashes due to depleted memory.

Interpretation of instructions without effect

How can we interpret the following program and its success?(Its obvious that there must not be any error message). I mean how does compiler interpret lines 2 and 3 inside main?
#include <stdio.h>
int main()
{
int a,b;
a; //(2)
b; //(3)
return 0;
}
Your
a;
is just an expression statement. As always in C, the full expression in expression statement is evaluated and its result is immediately discarded.
For example, this
a = 2 + 3;
is an expression statement containing full expression a = 2 + 3. That expression evaluates to 5 and also has a side-effect of writing 5 into a. The result is evaluated and discarded.
Expression statement
a;
is treated in the same way, except that is has no side-effects. Since you forgot to initialize your variables, evaluation of the above expression can formally lead to undefined behavior.
Obviously, practical compilers will simply skip such expression statements entirely, since they have no observable behavior.
That's why you should use some compilation warning flags!
-Wall would trigger a "statement with no effect" warning.
If you want to see what the compilation produces, compile using -S.
Try it with your code, with/without -O (optimization) flag...
This is just like you try something like this:
#include <stdio.h>
int main(void){
1;
2;
return 0;
}
As we can see we have here two expressions followed by semicolon (1; and 2;). It is a well formed statement according to the rules of the language.
There is nothing wrong with it, it is just useless.
But if you try to use though statements (a or b) the behavior will be undefined.
Of course that, the compiler will interpret it as a statement with no effect
L.E:
If you run this:
#include <stdio.h>
int main(void){
int a;
int b;
printf("A = %d\n",a);
printf("B = %d\n",b);
if (a < b){
printf("TRUE");
}else{
printf("FALSE");
}
return 0;
}
You wil get:
A = 0
B = 0
FALSE
Because a and b are set to 0;
Sentences in C wich are not control structures (if, switch, for, while, do while) or control statements (break, continue, goto, return) are expressions.
Every expression has a resulting value.
An expression is evaluated for its side effects (change the value of an object, write a file, read volatile objects, and functions doing some of these things).
The final result of such an expression is always discarded.
For example, the function printf() returns an int value, that in general is not used. However this value is produced, and then discarded.
However the function printf() produces side effects, so it has to be processed.
If a sentence has no side effects, then the compiler is free to discard it at all.
I think that for a compiler will not be so hard to check if a sentence has not any side effects. So, what you can expect in this case is that the compiler will choose to do nothing.
Moreover, this will not affect the observable behaviour of the program, so there is no difference in what is obtained in the resulting execution of the program. However, of course, the program will run faster if any computation is ignored at all by the compiler.
Also, note that in some cases the floating point environment can set flags, which are considered side-effects.
The Standard C (C11) says, as part of paragraph 5.1.2.3p.4:
An actual implementation need not evaluate part of an expression if it
can deduce that its value is not used and that no needed side effects
are produced [...]
CONCLUSION: One has to read the documentation of the particular compiler that oneself is using.

Passing parameters evaluation direction in macro

As I know in C, passing of actual parameters of a function evaluation starts from rightmost and directed to left.
What is the case for a macro definition with parameter? I made a code to make the sense clear but output confused me...
Here is the code.,
#define parsing(a,b) a*b
int parsefun(int a, int b)
{
return a*b;
}
int main()
{
int i=10;
printf("%d\n",parsing((i++),i));
i=10;
printf("%d\n",parsing(i,(i++)));
i=10;
printf("%d\n",parsefun((i++),i));
i=10;
printf("%d\n",parsefun(i,(i++)));
system("PAUSE");
return 0;
}
This code outputs,
100
100
100
110
I hoped same output for macros as function. But where is the crucial point here?
parsing of actual parameters of a function starts from rightmost and directed to left
I think you mean "evaluation" rather than "parsing". But that's not true, the C standard does not specify an order.
So the behaviour you're getting for the functions is unspecified by the C standard.
I hoped same output for macros as function
Macro arguments are not evaluated, they're simply substituted. So you end up with this:
int i=10;
printf("%d\n", (i++) * i);
i=10;
printf("%d\n", i * (i++));
After which, you're simply seeing undefined behaviour, as explained in this question: Why are these constructs (using ++) undefined behavior?.

Resources