I'm having hard time understanding nature of issue I encountered in my code.
Line
if ((struct.c == 0x02) && (struct2.c == 0x02) && (struct.s == !struct2.s))
{/**/}
where c is int and s is uint64_t produces
C4388:'==' signed/unsigned mismatch
warning. I understand what that warning is, I can't see what is triggering it here. What am I missing?
Directly quoting the C11 standard, chapter §6.5.3.3, (emphasis mine)
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....
So, the result of the logical ! operator is int, so !struct2.s produces int value, and the expression
....(struct.s == !struct2.s)
creates the issue.
NOTE 1:
I guess you use struct as a structure name just for illustration purpose, otherwise, struct being a reserved keyword in C you cannot use that as a variable name.
NOTE 2:
Maybe what you actually meant is (struct.s != struct2.s), but that's also just a (probable)guess.
FOOTNOTE :: Earlier question tagged C++ also, Moving it as footnote but keeping the info just for reference.
Regarding C++, the return type of ! is bool. Ref: C++11, chapter § 5.3.3 (again, emphasis mine)
The operand of the logical negation operator ! is contextually converted to bool(Clause 4); its value istrueif the converted operand isfalseand false otherwise. The type of the result is bool.
[too long for a comment]
To get the most out of compiler warnings, always try to put only one statement/expression on one line (at least temporarily when trying to determine the error's/warning's source).
So if you'd have set the code this way:
if (
(struct.c == 0x02)
&& (struct2.c == 0x02)
&& (struct.s == !struct2.s)
)
You'd been pointed by the compiler to exactly the (relativly) 4th line.
Related
I am a getting warning:
warning: '<<' in boolean context, did you mean '<' ? [-Wint-in-bool-context]
for the code similar to the following:
int a=7,b=3;
int index=((a<<1)||b)&&5;
To explain the rationale behind such warnings:
C did get a boolean type _Bool/bool as per C99, but no changes were done to the behavior of the various logical operators of the language. That is:
Equality operators ==/!=
Relational operators <,<=,>,>=
Logical AND &&
Logical OR ||
Logical negation !.
Despite C having a boolean type, all of these operators return type int with value 1 or 0. Unlike C++ where all of these operators actually return type bool with value true/false. This is a known flaw of C.
It's common good practice however to treat such expressions as if they were boolean. Coding guidelines like MISRA C encourage the use of a fictional type "essentially boolean", meaning any expression that could be treated as _Bool. The reason for this is that it makes code more self-documenting and also makes it harder to create various typo-related bugs.
For example if(str) could mean check for NULL, or it could mean check for null termination but oops we forgot to dereference. Same thing with if(*str). Whereas if we only pass the result of a logical operator to if, the code becomes much clearer and it becomes harders to write bugs: if(str != NULL) could only mean check for NULL and if(*str != '\0') could only mean check for null termination.
In your case, the || operator only cares if the operands are zero or non-zero ("essentially boolean"). In case a is non-zero then a<<1 will not change that. In case a is zero, then a<<1 is zero as well. Since the result is passed on to a logical operator, "in a boolean context", the shift is pointless - hence the warning. But of course a<<1 might take all kinds of other values in another context such as for example if(a<<1 & mask).
It would be reasonable to strongly suspect that you actually meant to write a<1 instead. Because that would yield either 0 or 1, where < is also a logical operator like ||.
I got the solution. We should avoid integers using with logical operators (eg. ||,&&). Using integers with bitwise operators (eg. <<,&,|,etc.) is fine.
Sometimes we don't get this problem while running on compilers because of low priority warning filters. In complex and warning sensitive compilers it comes up.
Thanks
How to get rid of MISRA violation on following statement
typedef unsigned char boolean;
boolean A, B;
A = !B;
Operand of logical ! operator is not an 'effectively Boolean'
expression. MISRA-C:2004 Rule 12.6; REFERENCE - ISO:C90-6.3.3.3 Unary
Arithmetic Operators
If you read rule 12.6 it says "check Boolean Expressions" in the appendix. There we can read
"Boolean-by-enforcement values can be introduced by implementing a specific type enforcement mechanism using a tool. A Boolean type could be associated with a specific typedef, and would
then be used for any objects that are Boolean. This could bring many
benefts, especially if the checking tool can support it, and in
particular it could help avoid confusion between logical operations
and integer operations."
MISRA-C:2004 assumes C90, and in C90 there is no bool type, you have to typedef it yourself, like you have done. Since your intention is to have a type which is effectively boolean, the code is just fine. In fact, your code follows MISRA recommendations beyond the mandatory ones.
The problem lies with your tool: it either does not support to allow a specific boolean type as per MISRA recommendations, or it is misconfigured.
Simple... don't use ! on things that aren't booleans. Just because your typedef is named boolean doesn't mean it is; it's still an unsigned char.
You could write:
if (b == 0) A = 1;
else A = 0;
I don't think MISRA allows ternary operators (could be wrong; not an expert) but if it does, you could write:
A = (b == 0) ? 1 : 0;
How about this:
A = (B == 0 ? 1 : 0);
Have you tried the idiom !! to convert values in boolean:
bool bool_val = !!int_val;
Then the far-fetched following code might work:
A = !(!!B) // B is "cast" within the parenthesis then we apply the "NOT"
Though the ISO:C90 standard says the operand can be of any scalar type the ! operator always yield a value of either 0 or 1; the underlying type (in MISRA-C:2004 terms) is considered effectively boolean, but the operand is not. Since the operator interprets its operand in a Boolean sense by comparing it 0 with try:
A = (B==0);
which make the logical comparison explicit. Also, depending on the tool, there may a boolean type enforcement mechanism you can configure for this typedef.
This question already has answers here:
What does !!(x) mean in C (esp. the Linux kernel)?
(3 answers)
Closed 9 years ago.
I've seen code where people have used conditional clauses with two '!'s
#define check_bit(var, pos) (!!((var) & (1 << (pos))))
#define likely(x) __builtin_expect(!!(x),1)
#define unlikely(x) __builtin_expect(!!(x),0)
are some of the examples I could find.
Is there any advantage in using !!(condition) over (condition)?
Well if the variable you are applying !! is not already a bool(either zero or one) then it will normalize the value to either 0 or 1.
With respect to __builtin_expect this kernel newbies thread discusses the notation and one of the responses explains (emphasis mine):
The signature of __builtin_expect
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) is:
long __builtin_expect (long exp, long c)
Note that the exp parameter should be an integral expression, thus no pointers
or floating point types there. The double negation handles the conversion from
these types to integral expressions automatically. This way, you can simply
write: likely(ptr) instead of likely(ptr != NULL).
For reference in C99 bool macro expands to _Bool, true expands to 1 and false expands to 0. The details are given in the draft standard section 7.16 Boolean type and values .
Logical negation is covered in 6.5.3.3 Unary arithmetic operators in paragraph 5:
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 unary ! logical negation operator, applied to any scalar, yields the int value 0 if its operand is non-zero, 1 if the operand is equal to zero. Quoting the standard:
The expression !E is equivalent to (0==E).
Applying ! twice to the same scalar value yields a result that's false if the value is false, true if the value is true -- but the result is normalized to 0 or 1, respectively.
In most cases, this isn't necessary, since any scalar value can be used directly as a condition. But in some cases you actually need a 0 or 1 value.
In C99 or later, casting the expression to _Bool (or to bool if you have #include <stdbool.h> behaves similarly and might be considered clearer. But (a) the result is of type _Bool rather than int, and (b) if you're using a pre-C99 compiler that doesn't support _Bool and you've defined your own bool type, it won't behave the same way as C99's _Bool.
The biggest I can see, is that it will force (or normalize) the value into 1 or 0 (that is a boolean value) regardless of how the x or var expression expands (e.g. char or double or int or etc.).
It casts to a boolean, which can sometimes be useful.
Is !!(x) guaranteed by the standard to return 0/1?
Note that I am not asking about c++, where a bool type is defined.
Yes, in C99, see §6.5.3.3/4:
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).
So !x and !!y can only yield 0 or 1, as ints.
For other operators, in C99, see also Is the "true" result of >, <, !, &&, || or == defined?
This is a comment really, but it's too long.
I found a very bizarre document while looking for the standard to answer your question: The New C Standard: An Economic and Cultural Commentary. And they say academia is under-funded. (Here is the full, 2083 page 10.5MB PDF. The former link is just the section on double negation.)
It has this to say on the subject of double negation:
A double negative is very often interpreted as a positive statement in English (e.g., “It is not unknown for double negatives to occur in C source”). The same semantics that apply in C. However, in some languages (e.g., Spanish) a double negative is interpreted as making the statement more negative (this usage does occur in casual English speech, e.g., “you haven’t seen nothing yet”, but it is rare and frowned on socially1).
I believe that the author would be happy knowing that this is of no use whatsoever in answering your real question (the answer to which is yes.)
Although I wouldn't have written it myself, what is the expected result of the following statement where A (guaranteed to zero or positive integer) is greater than 1?
return A || 1;
In many languages, I would expect A to be returned, unless the value of A is zero, in which case 1 would be.
I don't have my C book to hand, but I note that in reality, the value 1 always seems to be returned. Is this a result of compiler optimisation or given the potential ambiguity of the expression, is it that the return value is non-deterministic?
The standard says
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.
See section 6.5.14 of the standard.
The expected result is YES (or true)
|| operator returns true value if at least one of its operands is true (2nd operand in your code is obviously true)
This is straight C (no Objective-C involved). It will always return 1.
In C, the result of ||, &&, or ! is always 0 or 1, never any other non-zero value, regardless of the values of the operands. That means your A || 1 will always yield 1.
with C-based languages any nonzero value is true(represented by 1). And if your A is zero it will check the other comparisons if it's an OR comparison
Suffice to say, in your example, whatever the value of A is, will always return 1 even if you are using || 2. with 2 being nonzero, when performed with logical operator OR, will always return true(represented by 1)
I believe that the compiler will optimize and not even examine the value of A. Can someone confirm? I was under the impression that with A&&0, A||1, and A||0 (=A&&1), the compiler saves time by recognizing that the expression can be simplified to 0, 1, or A respectively.