I want to make one macro to check is a char Upper or Lower case. I know how to make it with two macros, but my question is: Is it possible to have nested if condition in macro definition in c? Something like this:
#define CHECK_CASE(x) (x >= 'a' && x <= 'Z') ? (x >='A' && x <='Z') ? 1 : 0 : 2
In the above case I always receive 2.
If you are use ASCII, then Z will have a lower value than a. So, for any value x, the condition (x >= 'a' && x <= 'Z') will be false.
In ASCII, the letters are not contiguous, so your technique for detecting an alphabetic letter is not correct.
C provides an API to check if a character is an alphabetic character or not, isalpha. But, the value returned by this API is checking for either isupper or islower. So, your macro could be written as:
#define CHECK_CASE(x) (isalpha(x) ? isupper(x) ? 1 : 0 : 2)
While isupper and islower could return any non-zero value to represent true, boolean negation (!) must result in either 0 or 1. We can use this to avoid needing to nest conditional expressions.
So, an alternative macro that retains your intended logic could be:
#define CHECK_CASE(x) (isalpha(x) ? !!isupper(x) : 2)
Or, we could flip the sense of the second test to avoid double negation:
#define CHECK_CASE(x) (isalpha(x) ? !islower(x) : 2)
The weakness of macros that uses its argument more than once is that if the argument is an expression, the expression gets evaluated multiple times. If the expression has a side-effect, the result of the macro may surprise the caller.
You can avoid this issue with an inline function instead:
inline int check_case(int x) {
return (isalpha(x) ? !islower(x) : 2);
}
Related
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);
What does this warning mean (i and j are not constants):
I have been trying to Google this but it does not give me any results.
warning: comparison of constant 10 with boolean expression is
always true [-Wtautological-constant-out-of-range-compare]
if ((0<=i<=10)&&(0<=j<=10)){
In my program, i and j are not constant values and they do change.
In C, chaining of relational operators like this are not valid design. Thus,
(0<=i<=10)
is not doing what you think it should be doing. it is getting evaluated as
((0<=i) <= 10 )
which is basically either
0 < = 10, producing 1 (considered TRUE value)
1 < = 10, also producing 1 (considered TRUE value)
sadly, both of which are way out than the expected path.
Solution: you need to break down your condtion check like
(0 <= i) && ( i<=10)
The other answers have already explained the core problem. You can use:
if ( ( ( 0 <= i) && (i <= 10)) && ( ( 0 <= i) && (i <= 10)) )
to resolve your problem.
My recommendation will be to wrap that logic in a function.
int isInRange(int x, int lower, int upper)
{
return (lower <= x && x <= upper);
}
and use
if ( isInRange(i, 0, 10) && isInRange(j, 0, 10) )
I believe you need to understand what's going on in your statement at a deeper level.
0<=i is a boolean expression, it will become true or false.
The result of that expression is then compared with 10.
So you end up with true <= 10 or false <= 10.
I think you meant to write
if ( ( 0 <= i ) && ( i <= 10 ) )
You cannot connect clauses together the way you did.
It means that the expression can be evaluated at compile time, and that the evaluation will not be compiled because it's true (ie. non-zero) at compile time.
Usually this happened to me when I accidentally used && instead of &. Which is not the case here of course, but it gives the same error message.
Also note that gcc makes a distinction between logical and bitwise:
Logical means bool which is either 0 meaning false or non-zero meaning true and the operator that yields these is && with keyword and.
Bitwise means boolean logic and the operator is & with keyword bitand.
&& Always yields a bool, which is true unless it's 0. If operating on bools they're equivalent, but on anything else & and && test different things ie. "Is it nonzero" vs "return only the matching bits".
int a;
scanf("%i", &a);
printf("%i", a&&1);
In this program, no matter the input it spits out a 1, even when I try even numbers. The only exception is when a = 0. I might not be understanding the AND operator correctly, but for any even number shouldn't the output be 0?
Because the && operator returns a non zero value if both its operands are not zero. Maybe you mean &.
int a;
if (scanf("%i", &a) == 1)
printf("%i", a & 1);
&& is the logical AND operator.
& is the bitwise AND operator.
Operator && is the logical AND operator that returns true/false.
In C language false is 0 (zero) otherwise 1 (one) for true as C does not have boolean type.
So the result of your operator is correct and as expected.
If you insist on using bool type you can include definition for it as below
// standard way
#include <stdbool.h>
which is basically
#define bool _Bool
#define true 1
#define false 0
i was just playing around with the ternary operator in my c class today. And found this odd behavior.
#include <stdio.h>
#include <stdbool.h>
main()
{
int x='0' ? 1 : 2;
printf("%i",x);
}
returns 1 as expected.But
#include <stdio.h>
#include <stdbool.h>
main()
{
int x='0'==true ? 1 : 2;
printf("%i",x);
}
returns 2 while i expect it to return 1.
The value of '0' is not zero, it is whatever integer value encodes the digit '0' on your system. Typically 48 (in encodings borring from ASCII), which is then not equal to true when interpreted as an integer, which is 1.
So the first of your code lines is equivalent to
int x = (48 != 0) ? 1 : 2;
which clearly evaluates to 1. The second is
int x = (48 == 1) ? 1 : 2;
which just as clearly evaluates to 2.
Maybe you are confusing '\0' and '0'
The value of the character constant
'\0'
is always 0 in C.
The value of the character constant
'0'
is implementation defined and depends on the character set. For ASCII, it is 0x30.
Also note that the macro true is defined to the value 1 and not 0.
That's because (assuming ASCII) '0' represents the integer 0x30, i.e. 48, and true represents the integer 1. So they're not equal.
In C, any nonzero value is considered true, but true itself is 1, and 1 is what you get from any built-in Boolean test (for example, 0 == 0 is 1).
true is defined as 1. '0' in ASCII is 0x30 which is not equal to 1.
Therefore the condition '0'==true is not true.
That's because '0' != true. The boolean value gets promoted to an integer type and is equal to 1 whereas '0' is equal to 48
'0' does not equal true, so the result of '0'==true is 0 (false). This is assigned to x and passed to the ternary operator, giving the result you see.
If you intended something else, you should use brackets to clarify the order of precedence you want, or break your code up into multiple statements.
As an exercise, I'd like to write a macro which tells me if an integer variable is signed. This is what I have so far and I get the results I expect if I try this on a char variable with gcc -fsigned-char or -funsigned-char.
#define ISVARSIGNED(V) (V = -1, (V < 0) ? 1 : 0)
Is this portable? Is there a way to do this without destroying the value of the variable?
#define ISVARSIGNED(V) ((V)<0 || (-V)<0 || (V-1)<0)
doesn't change the value of V. The third test handles the case where V == 0.
On my compiler (gcc/cygwin) this works for int and long but not for char or short.
#define ISVARSIGNED(V) ((V)-1<0 || -(V)-1<0)
also does the job in two tests.
If you're using GCC you can use the typeof keyword to not overwrite the value:
#define ISVARSIGNED(V) ({ typeof (V) _V = -1; _V < 0 ? 1 : 0 })
This creates a temporary variable, _V, that has the same type as V.
As for portability, I don't know. It will work on a two's compliment machine (a.k.a. everything your code will ever run on in all probability), and I believe it will work on one's compliment and sign-and-magnitude machines as well. As a side note, if you use typeof, you may want to cast -1 to typeof (V) to make it safer (i.e. less likely to trigger warnings).
#define ISVARSIGNED(V) ((-(V) < 0) != ((V) < 0))
Without destroying the variable's value. But doesn't work for 0 values.
What about:
#define ISVARSIGNED(V) (((V)-(V)-1) < 0)
This simple solution has no side effects, including the benefit of only referring to v once (which is important in a macro). We use the gcc extension "typeof" to get the type of v, and then cast -1 to this type:
#define IS_SIGNED_TYPE(v) ((typeof(v))-1 <= 0)
It's <= rather than just < to avoid compiler warnings for some cases (when enabled).
A different approach to all the "make it negative" answers:
#define ISVARSIGNED(V) (~(V^V)<0)
That way there's no need to have special cases for different values of V, since ∀ V ∈ ℤ, V^V = 0.
A distinguishing characteristic of signed/unsigned math is that when you right shift a signed number, the most significant bit is copied. When you shift an unsigned number, the new bits are 0.
#define HIGH_BIT(n) ((n) & (1 << sizeof(n) * CHAR_BITS - 1))
#define IS_SIGNED(n) (HIGH_BIT(n) ? HIGH_BIT(n >> 1) != 0 : HIGH_BIT(~n >> 1) != 0
So basically, this macro uses a conditional expression to determine whether the high bit of a number is set. If it's not, the macro sets it by bitwise negating the number. We can't do an arithmetic negation because -0 == 0. We then shift right by 1 bit and test whether sign extension occurred.
This assumes 2's complement arithmetic, but that's usually a safe assumption.
Why on earth do you need it to be a macro? Templates are great for this:
template <typename T>
bool is_signed(T) {
static_assert(std::numeric_limits<T>::is_specialized, "Specialize std::numeric_limits<T>");
return std::numeric_limits<T>::is_signed;
}
Which will work out-of-the-box for all fundamental integral types. It will also fail at compile-time on pointers, which the version using only subtraction and comparison probably won't.
EDIT: Oops, the question requires C. Still, templates are the nice way :P