Can we write multiple commands like in if statement {between brackets} in conditional operators ?
(For knowledge, not for use)
if (x == 1) {
printf("Printf");
scanf("%d", &scanf);
callFun(calling a function);
}
else if (x == 2) {
printf("Printf2");
scanf("%d", &scanf2);
callFun2(calling a function);
}
int foo(int x)
{
int g,h;
(void)( x == 1 ? ( printf("Hello\n"), scanf("%d", &g), callfunc(g)) : x == 2 ? ( printf("Hello2\n"), scanf("%d", &k), callfunc(h + 5)) : 0);
}
Very easy to read as you see. Better use ifs
This looks clean in my opinion
#include <stdio.h>
void func(){
puts("working");
}
void func1(){
puts("working 2");
}
int main(){
int i = 21;
i == 2122 ? func() : func1();
return 0;
}
This also works
int main(){
int i = 21;
i == 2122 ? (
puts("working 1"),
puts("working 2")
) : (
puts("working 3"),
puts("working 4"));
return 0;
}
The ?: is less generic than if since it requires operands that are expressions. Furthermore it requires both operands to be of the same type. In some cases when they aren't, C implicitly tries to convert them by applying the implicit "usual arithmetic conversions" on the 2nd and 3rd operands. This can lead to unexpected results. For example this code prints gibberish:
printf("%d\n", 1 ? 1 : 1.0);
Even though the 3rd operand is never evaluated, the 2nd operands gets implicitly promoted to double and printing that with %d gives undefined behavior.
To avoid subtle stuff like this, the ?: should be avoided most of the time. It's main purpose in the C language is actually to enable conditions inside function-like macros that return a value. For example we obviously can't write a macro returning a value like this:
#define M(cond) if(cond) { foo(); } else { bar(); }
But it could be done like this:
#define M(cond) ( (cond) ? foo() : bar() )
Similarly, the , comma operator's main purpose is also to enable such macros. So yeah, you could rewrite the code you've written with the ?: in combination with the comma operator. But it's a very bad idea since such code turns unreadable. The only place where it might be justified is inside a function-like macro:
#define M(x) ( x==1 ? (printf("Hello\n"), scanf("%d", &something), callFun(something)) \
: x==2 ? (printf("Hello2\n"), scanf("%d", &something), callFun2(something)) \
: 0 )
This macro would return whatever callFun and callFun2 returns, assuming they return compatible types.
And in case it isn't obvious, function-like macros like these are very bad practice and actual functions are always preferred when possible. Writing macros such as this is should be a last resort, like for example when maintaining some crappy code base where you can't change certain things.
It would be a weird and thus undesireable thing to do, but it can be done.
The key is to use a comma operator instead of separate statements.
(
x == 1 ? (
printf("Printf"),
scanf("%d", &scanf),
callFun(calling a function)
)
: x == 2 ? (
printf("Printf2"),
scanf("%d", &scanf2),
callFun2(calling a function)
)
: (void)0
);
Related
My purpose is trying to write a function as concise and short as possible.
int func(void)
{
int a;
return (
a = 42,
a++,
if (a > 42) a *= -1,
a);
}
I was expecting to return a -43. Instead I've got a compilation error.
My purpose is trying to write a function as concise and short as
possible.
int a;
return (
a = 42,
a++,
if (a > 42) a *= -1,
a);
Can simply be rewritten as:
return -43;
Or if that's too short for your liking, then you're looking for the conditional operator (colloquially referred to as the ternary operator), which has the form:
/* if a is logically true (does not evaluate to zero)
* then evaluate expression b, otherwise
* evaluate expression c
*/
a ? b : c;
So the return statement can be rewritten as:
a = 42;
return ++a > 42 ? -a : a;
As of your objective, then there's no merit to it. You should not write clever code. It harms readability and maintainability. (Although in this case, it doesn't)
Remember:
Simplicity is the
ultimate sophistication.
— Leonardo da Vinci
Any fool can write code
that a computer can
understand. Good
programmers write code
that humans can
understand. ― Martin
Fowler
Everything should be made
as simple as possible —
but no simpler. — Albert
Einstein (attributed).¹
[1] — credit: #SteveSummit
If your goal is writing the function don't write it in the main function. write it outside the main and call the function in main
The cause of your error is because of your statement expression there is an explanation here https://stackoverflow.com/a/45653540/14308832
So I guess you want to take a as parameter otherwise you can assign a as 42 in func
int func(int a){
a++;
return (a > 42 ? a *= -1 : a);
}
int main(void)
{
printf("%d",func(42));
}
Have you tried this?
int main(void)
{
int a;
return (a = 42, a++, a > 42 ? a = a * -1 : a);
}
Conditional operator in C is used like this:
condition ? value_if_true : value_if_false
What does 0 mean when it's used in the value_if_false?
I've seen some people using it like this, for example.
a == b ? i++ : 0
It seems like it does nothing. Does this work like return 0 in other functions?
In C language, ternary is shorter version of if statement and it requires both statements, if_true and if_false. It would be like this (in fact it can have multiple statements for one case, separated with comma):
Short:
condition ? if_true : if_false;
Long:
if (condition) {
if_true;
} else {
if_false;
}
You can also assign the value if you put something infront of condition.
Short:
result = condition ? if_true : if_false;
Long:
if (condition) {
result = if_true;
} else {
result = if_false;
}
Now here is the trick. In C language, writing 0; is a valid statement, so your ternary becomes in longer version same as code below:
if (a == b) {
i++;
} else {
0; /* This is valid C statement */
}
Or if you have assignment too, it would be:
if (a == b) {
result = i++;
} else {
result = 0;
}
You can also do this:
int a;
/* Code here ... */
condition ? a = 5: 0;
That is effectively the same as:
if (condition) {
a = 5;
} else {
/* DO not touch a */
}
The ?: operator is a ternary operator, but it is not called "ternary" as some answers and/or comments here suggest. It just is the arity of the operator, just as + is a binary operator or as & is unary. If it has a name at all, it is called "Conditional Expression"-operator
It is not quite equivalent to if/else, because it is a conditional value (with the consequence, that both expressions must have the same type) in the first place, not a conditional execution. Of course, both types can be cast to make them equal.
In the case of what the OP does, a better option (if if shall not be used) is in my opinion:
a == b && i++;
which resembles a bit more logical what happens. But of course it is a matter of style.
The reason why someone might want to write a == b ? i++ : 0; is that s/he probably wants to have an (Caution! You are now entering an opinion-based area) easier and faster alternative to if (a == b) i++; - although this is of course opinion-based and I personally not share the same opinion.
One thing I can think of as a "blocker" at the if statement is the requirement to write the parentheses () which can be omitted by using the conditional operator instead.
"But why the 0?"
The C syntax requires a third operand for the conditional operator. Else if you would want to compile for example:
a == b ? i++;
you will get an error from the compiler:
"error: expected ':' before ';' token"
Or respectively, doing so:
a == b ? i++ : ;
would raise:
"error: expected expression before ';' token"
So they use 0 as kind of "syntax satisfier" to be able to use the conditional operator as replacement for the if statement. You could use any other numeral value here as well, but 0 is the most readable value, which signifies that it has no use otherwise.
To showcase the use at an example:
#include <stdio.h>
int main (void)
{
int a, b, c = 4;
a = 2;
b = 2;
a == b ? c++ : 0;
printf("%d",c);
return 0;
}
The output for c will be 5, because a == b.
Note that a == b ? i++ : 0 is different when used f.e. inside of an assignment like f.e.:
int c = a == b ? i++ : 0;
Here c is either getting assigned by i or 0, dependent upon a == b is true or not. If a == b is true, c is assigned by i. If a == b is wrong, c is assigned by 0.
Side Notes:
To view it from a technical point, ?= is called the "conditional operator". The conditional operator is one of the group of ternary operators.
If you want to learn more about the conditional operator ?=, look at ISO:IEC 9899:2018 (C18), §6.5.15 - "Conditional operator" for more information.
There's nothing special about 0 one could write
a == b ? i++ : 1
And it would behave the same way.
Only difference is when you assign the expression to say another variable:
int c = a == b ? i++ : 1;
// a == b -> c will be i++
// a != b -> c will be 1
However it's much cleaner to write
if (a == b) i++;
It helps to think of the ternary operator as a shorthand way or writing an if-else statement.
If(a == b){
i++;
}else{
//if assigned, return 0. Else do nothing.
}
The program I'm trying to write includes a macro to round a real number to the nearest integer and a function which uses that macro to round an array of real numbers.
Here's the program:
#include <stdio.h>
#define SIZE 256
#define round(N) { return (N >=0)? (int)(N+0.5) : (int)(N-0.5) ; }
void round_array(int a[])
{
int i;
for(i=0; i <SIZE; i++)
{
a[i] = round(a[i]);
}
}
int main()
{
return 0;
}
While compiling, I'm getting these errors:
round.c: In function ���round_array���:
round.c:4:18: error: expected expression before ���{��� token
#define round(N) { return (N >=0)? (int)(N+0.5) : (int)(N-0.5) ; }
^
round.c:11:15: note: in expansion of macro ���round���
a[i] = round(a[i]);
^
round.c: At top level:
Why am I getting these errors and how can I fix them?
Because after preprocessing, your code will look similar to that:
a[i] = { return (a[i] >=0)? (int)(a[i]+0.5) : (int)(a[i]-0.5) ; }
If you like to stick to macro, declare it as:
#define round(N) ((N) >=0)? (int)((N)+0.5) : (int)((N)-0.5)
But this is still not really correct because of int/float mixing. That is however already a different topic.
Like it was told to you in a comment, macros aren't functions. They are a token substitution mechanism. So you do not return from them as you would a function.
#define round(N) (((N) >=0)? (int)((N)+0.5) : (int)((N)-0.5))
The changes I made include:
Making it an expression. This involves replacing the curly braces with parentheses. This is so you could use the macro almost anywhere you could use a function. Had I left the curly braces it would have been a compound statement.
Wrapping the parameter N in parentheses as well, to make sure operator precedence doesn't come back and bite us.
Macro-replacement is basically what it sounds like, it replaces the macro with the body of the macro, quite literally.
So when you have
a[i] = round(a[i]);
It will be replaced by
a[i] = { return (a[i] >=0)? (int)(a[i]+0.5) : (int)(a[i]-0.5) ; };
That's not valid syntax. The right-hand side of an assignment must be an expression and not a statement.
A simple solution is to turn round from a macro to an actual function. An even simpler solution is to realize that int values (a[i] is an int) doesn't have fractions, so there's nothing to round.
If you want to use floating-point values though, the correct solution is to use the standard round function, not to make up your own.
If you insist on writing this yourself, you should replace the icky macro with a safer, cleaner function:
inline int int_round (double d)
{
return (int) ( d >= 0 ? d+0.5 : d-0.5 );
}
This should yield the very same machine code.
You don't need the return keyword, it's not a function. Get rid of it.
Quoting C11, chapter §6.8.6.4
A return statement terminates execution of the current function and returns control to
its caller. [...]
which is not the purpose of your MACRO definition. Inclusion of return keyword is unwanted and invalid syntax there.
What you probably want is a syntax like
(N >=0)? (int)(N+0.5) : (int)(N-0.5)
or, something better
( (N) >=0)? (int)((N)+0.5) : (int)((N)-0.5)
without the return and maybe the trailing ; also.
A friend of mine jokingly asked me this question. It was meant to be a "goes without saying" type remark, but then I actually thought about it for a while and started coming up with some clever "almost solutions".
First attempt:
If C ever supports quantum computing there may be an answer to this. A q-bit can be in many states at once, so it could be false AND true and this conditional will return (BOOL)0.5 aka "Yes/no/maybe-so" - but once you observe the variable the whole thing will collapse and become invalid again.
Second attempt:
If X could somehow be defined as a random binary generator and you cast it to a BOOL you could get false some of the time. I'm not sure if you can do this though in C unless you use CLANG. #define x (BOOL)!!(rand()%2)
The language we were discussing this in is C but I'm also curious if anyone can find any solutions in any language.
When x is volatile (volatile int x) and is modified by an external thread / device, the expression can be false.
It's a bit of a trick, but the following solution also works:
#define x 1 ? 0 : 1
(x || !x)
The reason is in the operator precedence. After preprocessing (x || !x) resolves to the following (parentheses added to show the precedence):
(1 ? 0 : (1 || !1) ? 0 : 1)
Macros are really cheating here, but you don't need anything to do with boolean types or special compilers. The following, as far as I know, is legal standard C.
#include <stdio.h>
int f(void) {
static int y = 0;
if (y == 0) {
y = 1;
return 0;
} else {
return 1;
}
}
#define x f()
int main(void) {
if (x || !x) {
puts("It was true");
} else {
puts("It was false");
}
return 0;
}
Or even more concisely:
int y = 0;
#define x y++
(For those worried about undefined behavior, note there is a sequence point between the left and right side of ||.)
An even simpler macro:
#define x 0&0
expanding (x || !x) gives (0 & 0 || !0 & 0) which is always false.
Similarly:
#define x 0*0
#define x 1*0 // for binary buffs
#define x 4&2 // for HHGG fans.
I could not find a 2 letter macro :(
Tried in JS:
var i = 0
i++ || !(i++)
Note: this solution works only when i = 0
can every if...then...else statement be converted into an equivalent statement using only ?:
The code:
if ( flag ) {
exit(1);
}
else {
return 0;
}
cannot be converted into:
flag ? exit(1) : return 0;
A better example - this would be inside a loop:
if ( flag ) {
continue;
}
else {
break;
}
cannot be converted to:
flag ? continue : break;
While any use I can think of for the ternary operator can be implemented as an if/else, the converse is not true; at least not without resorting to perverse and pointless 'tricks' that yield no benefit in terms of performance, readability, or maintainability.
The syntax of if/else is:
if( <boolean expression> )
<statment>|<statment block>
else
<statment>|<statment block>
whereas the syntax of the ?: ternary operator is:
<boolean expression> ? <expression> : <expression> ;
The important thing here being that an <expression> and a <statement> are different syntactic elements.
The very limited usage of the form:
if( b ) x = y else x = z ;
can be implemented as:
x = b ? y : x ;
but here the restriction is that the same variable is being assigned in both the true and false clauses, (and therefore y and z are both at least convertible to the type of x). So it may be said that any conditional assignment can be implemented with the ternary operator (after all that is its primary purpose).
Now since a function call is a valid expression, you could wrap the true and false clauses in separate functions, but to do that simply to prove a point is somewhat perverse:
if( b )
true_stuff() ;
else
false_stuff() ;
is equivalent to:
b ? true_stuff() : false_stuff() ;
and those functions can contain any code at all.
So to convert the more general if/else case to a ?: operation, the true/false statement blocks must first be wrapped in separate functions. However even then Neil Butterworth's examples will defeat this approach since the behaviour of break, continue, and return affect control flow beyond the confines of the if/else construct, (although perhaps those are also examples of code you want to avoid!). The presence of a goto in the if/else would also defeat this approach. .
I think in the end, even if you could, why would you want to?
No.
Both "branches" of the conditional expression must evaluate to the same type, and that type must not be void.
For example, you could do this:
x > 0 ? printf("Positive!\n") : 0;
because printf return int. (I would only use this in a round of code golf, though; in fact, I just did.)
But you cannot do this:
x > 0 ? exit() : 0;
because exit returns void (or, actually, doesn't return at all).