In an if statement I want to include a range, e.g.:
if(10 < a < 0)
but by doing so, I get a warning "Pointless comparison". However, this works fine without any warning:
if(a<10 && a>0)
Is the first case possible to implement in C?
Note that the original version if(10 < a < 0) is perfectly legal. It just doesn't do what you might (reasonably) think it does. You're fortunate that the compiler recognized it as a probable mistake and warned you about it.
The < operator associates left-to-right, just like the + operator. So just as a + b + c really means (a + b) + c, a < b < c really means (a < b) < c. The < operator yields an int value of 0 if the condition is false, 1 if it's true. So you're either testing whether 0 is less than c, or whether 1 is less than c.
In the unlikely case that that's really what you want to do, adding parentheses will probably silence the warning. It will also reassure anyone reading your code later that you know what you're doing, so they don't "fix" it. (Again, this applies only in the unlikely event that you really want (a < b) < c).)
The way to check whether a is less than b and b is less than c is:
a < b && b < c
(There are languages, including Python, where a < b < c means a<b && b<c, as it commonly does in mathematics. C just doesn't happen to be one of those languages.)
It's not possible, you have to split the check as you did in case 2.
No it is not possible.
You have to use the second way by splitting the two conditional checks.
The first does one comparison, then compares the result of the first to the second value. In this case, the operators group left to right, so it's equivalent to (10<a) < 0. The warning it's giving you is really because < will always yield 0 or 1. The warning is telling you that the result of the first comparison can never be less than 0, so the second comparison will always yield false.
Even though the compiler won't complain about it, the second isn't really much improvement. How can a number be simultaneously less than 0, but greater than 10? Ideally, the compiler would give you a warning that the condition is always false. Presumably you want 0<a<10 and a>0 && a<10.
You can get the effect of the second using only a single comparison: if ((unsigned)a < 10) will be true only if the number is in the range 0..10. A range comparison can normally be reduced to a single comparison with code like:
if ((unsigned)(x-range_start)<(range_end-range_start))
// in range
else
// out of range.
At one time this was a staple of decent assembly language programming. I doubt many people do it any more though (I certainly don't as a rule).
As stated above, you have to split the check. Think about it from the compiler's point of view, which looks at one operator at a time. 10 < a = True or False. And then it goes to do True/False < 0, which doesn't make sense.
no,this is not valid syntax of if statement,it should have a valid constant expression,or may have logical operators in them,and is executed only,when the expression in the bracket evaluates to true,or non zero value
Related
In an if statement I want to include a range, e.g.:
if(10 < a < 0)
but by doing so, I get a warning "Pointless comparison". However, this works fine without any warning:
if(a<10 && a>0)
Is the first case possible to implement in C?
Note that the original version if(10 < a < 0) is perfectly legal. It just doesn't do what you might (reasonably) think it does. You're fortunate that the compiler recognized it as a probable mistake and warned you about it.
The < operator associates left-to-right, just like the + operator. So just as a + b + c really means (a + b) + c, a < b < c really means (a < b) < c. The < operator yields an int value of 0 if the condition is false, 1 if it's true. So you're either testing whether 0 is less than c, or whether 1 is less than c.
In the unlikely case that that's really what you want to do, adding parentheses will probably silence the warning. It will also reassure anyone reading your code later that you know what you're doing, so they don't "fix" it. (Again, this applies only in the unlikely event that you really want (a < b) < c).)
The way to check whether a is less than b and b is less than c is:
a < b && b < c
(There are languages, including Python, where a < b < c means a<b && b<c, as it commonly does in mathematics. C just doesn't happen to be one of those languages.)
It's not possible, you have to split the check as you did in case 2.
No it is not possible.
You have to use the second way by splitting the two conditional checks.
The first does one comparison, then compares the result of the first to the second value. In this case, the operators group left to right, so it's equivalent to (10<a) < 0. The warning it's giving you is really because < will always yield 0 or 1. The warning is telling you that the result of the first comparison can never be less than 0, so the second comparison will always yield false.
Even though the compiler won't complain about it, the second isn't really much improvement. How can a number be simultaneously less than 0, but greater than 10? Ideally, the compiler would give you a warning that the condition is always false. Presumably you want 0<a<10 and a>0 && a<10.
You can get the effect of the second using only a single comparison: if ((unsigned)a < 10) will be true only if the number is in the range 0..10. A range comparison can normally be reduced to a single comparison with code like:
if ((unsigned)(x-range_start)<(range_end-range_start))
// in range
else
// out of range.
At one time this was a staple of decent assembly language programming. I doubt many people do it any more though (I certainly don't as a rule).
As stated above, you have to split the check. Think about it from the compiler's point of view, which looks at one operator at a time. 10 < a = True or False. And then it goes to do True/False < 0, which doesn't make sense.
no,this is not valid syntax of if statement,it should have a valid constant expression,or may have logical operators in them,and is executed only,when the expression in the bracket evaluates to true,or non zero value
In an if statement I want to include a range, e.g.:
if(10 < a < 0)
but by doing so, I get a warning "Pointless comparison". However, this works fine without any warning:
if(a<10 && a>0)
Is the first case possible to implement in C?
Note that the original version if(10 < a < 0) is perfectly legal. It just doesn't do what you might (reasonably) think it does. You're fortunate that the compiler recognized it as a probable mistake and warned you about it.
The < operator associates left-to-right, just like the + operator. So just as a + b + c really means (a + b) + c, a < b < c really means (a < b) < c. The < operator yields an int value of 0 if the condition is false, 1 if it's true. So you're either testing whether 0 is less than c, or whether 1 is less than c.
In the unlikely case that that's really what you want to do, adding parentheses will probably silence the warning. It will also reassure anyone reading your code later that you know what you're doing, so they don't "fix" it. (Again, this applies only in the unlikely event that you really want (a < b) < c).)
The way to check whether a is less than b and b is less than c is:
a < b && b < c
(There are languages, including Python, where a < b < c means a<b && b<c, as it commonly does in mathematics. C just doesn't happen to be one of those languages.)
It's not possible, you have to split the check as you did in case 2.
No it is not possible.
You have to use the second way by splitting the two conditional checks.
The first does one comparison, then compares the result of the first to the second value. In this case, the operators group left to right, so it's equivalent to (10<a) < 0. The warning it's giving you is really because < will always yield 0 or 1. The warning is telling you that the result of the first comparison can never be less than 0, so the second comparison will always yield false.
Even though the compiler won't complain about it, the second isn't really much improvement. How can a number be simultaneously less than 0, but greater than 10? Ideally, the compiler would give you a warning that the condition is always false. Presumably you want 0<a<10 and a>0 && a<10.
You can get the effect of the second using only a single comparison: if ((unsigned)a < 10) will be true only if the number is in the range 0..10. A range comparison can normally be reduced to a single comparison with code like:
if ((unsigned)(x-range_start)<(range_end-range_start))
// in range
else
// out of range.
At one time this was a staple of decent assembly language programming. I doubt many people do it any more though (I certainly don't as a rule).
As stated above, you have to split the check. Think about it from the compiler's point of view, which looks at one operator at a time. 10 < a = True or False. And then it goes to do True/False < 0, which doesn't make sense.
no,this is not valid syntax of if statement,it should have a valid constant expression,or may have logical operators in them,and is executed only,when the expression in the bracket evaluates to true,or non zero value
I wanted to know if there's a way to omit second or third part of the ternary operator?
I already read this and similar ones but they didn't help.
What I specifically want is something like:
x == y ? x*=2;
however this gives me error as gcc expects another expression also. So are:
x == y ? x *=2 : continue;
x == y ?: x /=2;
What can I do in these situations except:
if(x == y) do_something;
Edit for further clarification:
As my question seems to be confusing and got all kinds of comments/answers my point was when thinking logically, an else is required after if , so is the default statement in a switch however, neither are mandatory. I was asking if it's the case with ?: also and if so, how.
I wanted to know if there's a way to omit second or third part of the ternary operator?
No, not in standard C.
You can substitute expressions or statements that do not use the conditional operator at all, but in standard C, the conditional operator requires three operands, just like the division operator (/) requires two. You cannot omit any.
Nor is it clear why you want to do. The primary thing that distinguishes the conditional operator from an if [/ else] statement is that expressions using the conditional operator are evaluated to produce values. If you're not interested in that value then using a conditional expression instead of a conditional statement is poor style. A standard if statement is much clearer, and clarity is king. This is a consideration even when you do want the value.
What can I do in these situations except:
if(x == y) do_something;
You can go have a coffee and hope the mood passes.
But if it doesn't, then the logical operators && and || have short-circuiting behavior that might suit, as #EricPostpischil already observed:
a && b is an expression analogous to if (a) b;. It evaluates a, after which there is a sequence point. If a was truthy then it evaluates b and that is the result of the expression; otherwise it does not evaluate b and the value of a is the value of the expression. That is the C version of the hypothetical a ? b : (nothing), and why C does not need the latter.
Similarly, a || b is an expression analogous to if (!a) b;. b is evaluated and yields the result of the expression if and only if a is falsey. That is the C version of the hypothetical a ? (nothing) : b.
But here again, it is poor C style to use && and || expressions exclusively for their side effects. If you don't care about the result of the operation, then use an if statement.
Or perhaps poor style is the point? If you're shooting for an entry in the International Obfuscated C Code Contest then abusing operators is par for the course. In that case, you could consider rewriting your expressions to use the ternary operator after all. For example,
x == y ? x *=2 : continue;
could be written as x *= ((x == y) ? 2 : 1), provided that you weren't actually trying to get loop-cycling behavior out of that continue. And
x == y ?: x /=2;
could be rewritten similarly. Though if you were actually looking toward IOCCC, then there are better obfuscation options available.
For the purpose asked about in this question, in which the result value of the conditional operator would not be used:
For a ? b : c without b you can use a && b, which will evaluate b if and only if a is true.
For a ? b : c without c you can use a || c, which will evaluate c if and only if a is false.
These expressions will have different values than a ? b : c, but that does not matter when the value is not used.
Without some exceptional circumstance to justify this, most experienced programmers would consider it bad practice.
GCC has an extension that uses the first operand for a missing second operand without evaluating it a second time. E.g. f(x) ? : y is equivalent to f(x) ? f(x) : y except that f is only called once.
Similar to the 'hyphen-ish' character of "-1" being called "unary minus", "?:" is called "trenary" because it requires 3 parts: the condition, the "true" case statement and the "false" case statement. To use "?:" you must supply 3 "terms".
Answering the question in the title, no, you cannot omit one part.
The following responds to "What can I do in these situations except:"
Given that your two examples show an interest in performing (or not) a mathematical operation on the variable 'x', here is a "branchless" approach toward that (limited) objective. ("Branchless" coding techniques seek to reduce the impact of "branch prediction misses", an efficiency consideration to reduce processing time.)
Note: the for() loop is only a "test harness" that presents 3 different values for 'y' to be compared to the value of 'x'. The variable 'n' makes more obvious your OP constant '2'. Further, as you are aware, performing multiplication OR division are two completely different operations. This example shows multiplication only. (Replace the '*' with '/' for division with the standard caveat regarding "division by zero" being undefined.) Depending on the probability of "cache misses" and "branch prediction" in modern CPUs, this seemingly complex calculation may require much less processing time than a 'true/false branch' that may bypass processing.
int n = 2; // multiplier
for( int y = 4; y <= 6; y++ ) { // three values for 'y'
int xr = 5; // one value for 'xr'egular
int xb = 5; // same value for 'xb'ranch
(xr == y) ? xr *= n : 1; // to be legitimate C
// when x == y the rhs becomes (n-1)*(1)+1 which equals n
// when x != y the rhs becomes (n-1)*(0)+1 which equals 1 (identity)
// Notice the rhs includes a conditional
// and that the entire statement WILL be evaluated, never bypassed.
xb *= ((n-1)*(xb==y))+1;
printf( "trenaryX = %2d, branchlessX = %2d\n", xr, xb );
}
Output
trenaryX = 5, branchlessX = 5
trenaryX = 10, branchlessX = 10
trenaryX = 5, branchlessX = 5
I hope this makes clear that "trenary" means "3 part" and that this digression into "branchless coding" may have broadened your horizons.
You can use the fact that the result of comparison operators is an int with value 0 or 1...
x == y ? x*=2;
x *= (x == y) + 1; // multiply by either 1 or 2
But a plain if is way more readable
if (x == y) x *= 2;
x == y ? x*=2 : 1;
The syntax requires all three parts... But, if you write code like this, you will lose popularity at the office...
Repeating for those who might have missed it: The syntax requires all three parts.
Actually, you shouldn't do this because as #user229044 commented, "if (x==y) do_something; is exactly what you should do here, not abuse the ternary operator to produce surprising, difficult-to-read code that can only cause problems down the line. You say "I need to know if that's possible", but why? This is exactly what if is for."
As in ternary operator without else in C, you can just have the third/second part of the ternary operator set x to itself, for example, you can just do:
x = (x == y ? x *= 2 : x);
or
x == (y ? x : x /= 2);
In an if statement I want to include a range, e.g.:
if(10 < a < 0)
but by doing so, I get a warning "Pointless comparison". However, this works fine without any warning:
if(a<10 && a>0)
Is the first case possible to implement in C?
Note that the original version if(10 < a < 0) is perfectly legal. It just doesn't do what you might (reasonably) think it does. You're fortunate that the compiler recognized it as a probable mistake and warned you about it.
The < operator associates left-to-right, just like the + operator. So just as a + b + c really means (a + b) + c, a < b < c really means (a < b) < c. The < operator yields an int value of 0 if the condition is false, 1 if it's true. So you're either testing whether 0 is less than c, or whether 1 is less than c.
In the unlikely case that that's really what you want to do, adding parentheses will probably silence the warning. It will also reassure anyone reading your code later that you know what you're doing, so they don't "fix" it. (Again, this applies only in the unlikely event that you really want (a < b) < c).)
The way to check whether a is less than b and b is less than c is:
a < b && b < c
(There are languages, including Python, where a < b < c means a<b && b<c, as it commonly does in mathematics. C just doesn't happen to be one of those languages.)
It's not possible, you have to split the check as you did in case 2.
No it is not possible.
You have to use the second way by splitting the two conditional checks.
The first does one comparison, then compares the result of the first to the second value. In this case, the operators group left to right, so it's equivalent to (10<a) < 0. The warning it's giving you is really because < will always yield 0 or 1. The warning is telling you that the result of the first comparison can never be less than 0, so the second comparison will always yield false.
Even though the compiler won't complain about it, the second isn't really much improvement. How can a number be simultaneously less than 0, but greater than 10? Ideally, the compiler would give you a warning that the condition is always false. Presumably you want 0<a<10 and a>0 && a<10.
You can get the effect of the second using only a single comparison: if ((unsigned)a < 10) will be true only if the number is in the range 0..10. A range comparison can normally be reduced to a single comparison with code like:
if ((unsigned)(x-range_start)<(range_end-range_start))
// in range
else
// out of range.
At one time this was a staple of decent assembly language programming. I doubt many people do it any more though (I certainly don't as a rule).
As stated above, you have to split the check. Think about it from the compiler's point of view, which looks at one operator at a time. 10 < a = True or False. And then it goes to do True/False < 0, which doesn't make sense.
no,this is not valid syntax of if statement,it should have a valid constant expression,or may have logical operators in them,and is executed only,when the expression in the bracket evaluates to true,or non zero value
Suppose we have an int and want to toggle it between 0 and 1 in a boolean fashion. I thought of the following possibilities:
int value = 0; // May as well be 1
value = value == 0 ? 1 : 0;
value = (value + 1) % 2;
value = !value; // I was curious if that would do...
The third one seems to work. Why? Who decides that !0 is 1?
Is something wrong with any of these?
Are there other possibilities? e.g. bitwise operators?
Which offers the best performance?
Would all that be identical with _Bool (or bool from stdbool.h)? If not, what are the differences?
EDIT: Many great answers with lots of valuable information, thanks! Unfortunately, I can only accept one.
value = !value; expresses what you want to do directly, and it does exactly what you want to do by definition.
Use that expression.
From C99 6.5.3.3/5 "Unary arithmetic operators":
The result of the logical negation operator ! is 0 if the value of its
operand compares unequal to 0, 1 if the value of its operand compares
equal to 0. The result has type int. The expression !E is equivalent
to (0==E).
The third one seems to work. Why? Who decides that !0 is 1?
C Standard guarantees that !0 is 1.
Are there other possibilities? e.g. bitwise operators?
Yes, you can use the exclusive OR operator:
value ^= 1;
By the way I prefer this to value = !value; as relational and equality operators can result to branching and bitwise operators usually do not.
value = 1 - value; // toggle from 0 to 1 ... or 1 to 0
// when you know initial value is either 0 or 1
the language was designed that way.
Use the 3rd one, the others are right but unnecessarly complicated and therefore hiding the intent.
value = (value ^ 1) & 1;
They're all the same after optimisation.
_Bool would have the same results. The only thing different with _Bool is that values are coerced to be either 1 or 0. Meaning that bool x = 55; will have the value x == 1
EDIT: Corrected the formula in 3 because of my brainfart. I let the comments so that people can see my blooper.
value = !value seems the most reasonable one, but you can also use value = 1 - value or value ^= 1. But the last two would both break if value is not 0 or 1. The first one would still work.
There can be noticeable performance issues with the alternatives depending on the architecture:
!a might need in some architectures comparison and branching, which can be expensive depending on the pattern of 'a'
on some architectures there is conditional move (which is branchless), but
which may require still 3 instructions to complete (with dependencies)
1-a most likely needs two instructions in many architectures
counter example: ARM has reverse subtraction RSB %r0, %r0, #1
1^a can be implemented in many architecture with a single instruction
a=(a+1) % 2 will be most likely optimized to a=(a+1)&1, which requires 2 instructions
But anyway the first rule of optimization is that don't optimize a non working code.
To replace !a with a^1, one has to be 100% certain that it produces always the expected value.
Your expression value = value == 0 ? 1 : 0; will work exactly like value = !value;. You can use any of the two.
!0 is always 1 and also !(any non zero value) is 0
Use bitwise NOT operator
var = ~var;