This question already has answers here:
!! c operator, is a two NOT?
(4 answers)
What is "!!" in C? [duplicate]
(7 answers)
Closed 8 years ago.
doing some exam prep and this is a past question.
Describe what the following pieces of C do and re write in a simple programming style with the same functionality.
(The bad indentation was the intention of the question).
With regards to section A i'm not sure what unsigned cast is doing to a. I have tested it a few times and can't seem to get a result that makes sense.
Similarly In B im not sure what how the while loop is working with the long cast and the !! being another problem
The Code :
//code section A
int f(int a,int b){
return(((unsigned) a)>b);}
//code section B
int h(int *x, int y){
int * z= x-- +y;
w=0;
while( (long) z-- ^(long) x) w += !!(*z);
return w;}
Any help would be appreciated, Thank you.
!! negates a boolean expression twice, essentially converting an expressions value to 0 or 1.
As in C all values other than zero mean true, and zero means false, !! can be used to convert it into 0 or 1, in the case you need to use it later in a function or expression which doesn't accept any value for true, only the number 1.
About the rest: unsigned interprets the internal representation of your int a from your function argument to unsigned int, so for example -1 becomes 4294967295 if your compiler uses two's complement and 4 byte ints.
About the casting to long : I strongly recommend against in similar situations unless you absolutely know what you are doing. In your example, it does some pointer arithmetic, in interpreting your pointer as numeric values, essentially working with the addresses of your variables as if they were just numbers. They have probably chosen long because on their system it had the exact same size as a pointer. This is not guaranteed to be so on all systems.
So, to give a very short answer to your question: The code does undefined behavior with those expressions, except for the !! which just give 0 if the expression was zero, and 1 otherwise.
The operator ! is the logical negation.
!true is false (0), and !false is true (1).
When a value is used as a boolean value, anyhting other than 0 (0 in a large sense) is true; 0 is false.
So, !!(*z) has either the value 0 or 1.
It will be 0 if *z was NULL to begin with
It will be 1 if *z was not NULL.
! is the boolean operator for not.
false is 0, and true is 1 in C.
So when you take any int, which is not 0- and you run ! on it, you'll get 0 (true becomes false), and zero will become one .
So the action of !! is changing each non-zero value to 1 , and leaving each 0 a 0.
Related
Given that x is a variable of type int with the number 5 as its value, consider the following statement:
int y = !!x;
This is what I think it happens: x is implicitly casted to a bool and the first negation is executed, after that the last negation is made, so a cast and two negations.
My question is, isn't just casting to bool (executing int y = (bool)x; instead of int y = !!x) faster than using double negation, as you are saving two negations from executing.
I might be wrong because I see the double negation a lot in the Linux kernel, but I don't understand where my intuition goes wrong, maybe you can help me out.
There was no bool type when Linux was first written. The C language treated everything that was not zero as true in Boolean expressions. So 7, -2 and 0xFF are all "true". No bool type to cast to. The double negation trick ensures the result is either zero or whatever bit pattern the compiler writers chose to represent true in Boolean expressions. When you're debugging code and looking at memory and register values, it's easier to recognize true values when they all have the same bit patterns.
Addendum: According the C89 draft standard, section 3.3.3.3:
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 while there was no Boolean type in the early days of the Linux OS, the double negation would have yielded either a 0 or a 1 (thanks to Gox for pointing this out), depending on the truthiness of the expression. In other words any bit pattern in the range of INT_MIN..-1 and 1..INT_MAX would have yielded a 1 and the zero bit pattern is self-explanatory.
C language unlike other languages does not have bool type. bool in C is actually defined in stdbool.h which is not included in many C projects. Linux kernel is one such projects, it would be a pain to go through Linux code and update everything to use bool now as well. That is reason why Linux kernel does not use bool in C.
why !!x? This is done to ensure that value of y is either 1 or 0. As an example if you have this cocd
x=5;
int y = !!x;
We know that everything that non-zero values in C mean true. So above code would brake down to y= !!(5) followed by y = !(0) and than y = 1.
EDIT:
One more thing, I just saw OP mentioned casting to bool. In C there is no bool as base type, bool is defined type, thus compilers do not cast integers to Boolean type.
EDIT 2:
To further explain, in C++, Java and other languages when you type bool a = false you do not have to use headers or compile some other libraries or define bool type for bool type to work, it is already incorporated into compilers, where as in c you have to.
EDIT 3:
bool is not the same as _Bool.
The only reason I can imagine is because this saves some typing (7 chars vs 2 chars).
As #jwdonahue and #Gox have already mentioned, this is not the correct reason. C did not have bool when the linux kernel was written therefore casting to bool was not an option.
As far as efficiency goes, both are equivalent because compilers can easily figure this out. See https://godbolt.org/g/ySo6K1
bool cast_to_bool_1(int x) {
return !!x;
}
bool cast_to_bool_2(int x) {
return (bool) x;
}
Both the functions compile to the same assembly which uses the test instruction to check if the argument is zero or not.
test edi, edi // checks if the passed argument is 0 or not
setne al // set al to 0 or 1 based on the previous comparison
ret // returns the result
This question already has answers here:
sizeof() operator in if-statement
(5 answers)
Closed 4 years ago.
Please give the reason for the output...why it's giving 'bye' while the condition if statement is true because the size of int is 2 or 4 byte.
#include<stdio.h>
#include<conio.h>
int main()
{
if(sizeof(int)>-1)
printf("hi");
else
printf("bye");
return 0;
}
See http://en.cppreference.com/w/c/language/sizeof
Both versions return a value of type size_t.
See size_t, http://en.cppreference.com/w/c/types/size_t
which states that it is unsigned.
If therefor the comparison is effectively with a high positive value,
then the logical expression is basically always false.
If you would help the compiler understand what you really want to do,
e.g. by changing to
((int)sizeof(int))>-1
things are different.
It's because the return type of sizeof() is size_t and sizeof() never gives size in negative bytes.
sizeof(int) results is type of unsigned.
And here
if(sizeof(int)>-1)
Comparison is happening between different types i.e signed(-1) and unsigned. So internally compiler will do implicit typecasting i.e signed gets converted into unsigned and -1 equivalent unsigned value is all one's i.e 4294967295.
So now condition looks like
if(4 > 4294967295)
Which is false so it prints bye.
See this for sizeof() return type http://en.cppreference.com/w/c/types/size_t
This question already has answers here:
Return value of "==" operator in C
(4 answers)
Closed 5 years ago.
To test "What does this expression, 1>0, evalutes to (on 64 bit) in C?" question, I wrote this program.
int main()
{
printf("char=%d", 1>0 );
return 0;
}
It prints "1". Is it right way to find the expression, 1>0?
And does operating system bit (64bit) matter? Why did the problem state (on 64 bit)???
In C, a > b is an expression of int type that is either equal to 0 or 1. That is not a function of the operating system: of course though the exact nature of an int is dependent on your platform.
So 1 > 0 is an int with value 1.
So your code is equivalent to printf("char=%d", 1);
According to C11 Standard, Section 6.5.8: Relational operators -
6. Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false, The result has type int.
The Footnote (which is very important to understand) says,
The expression a<b<c is not interpreted as in ordinary mathematics. As the syntax indicates, it means (a<b)<c; in other words, 'if a is less than b, compare 1 to c; otherwise, compare 0 to c'.
So,
printf("char=%d", 1>0 );
is evaluated as
printf("char=%d", 1 );
The same way if,
int num = 0xAA;
int mun = 0x55;
printf("char=%d", 0xAA>0x55 );
The result will be
1
Update: The whole confusion about 32-bit vs 64-bit system is irrelevant for this particular issue you are facing. You don't need to consider that as of now.
In C, true is represented by 1(one) or any nonzero value and false is represented by 0(zero). As 1>0 is true you get a 1 which represents true. All relational operators work the same way. It works the same on 16 bit,32 bit and 64 bit machine.
This question already has answers here:
How does logical negation work in C?
(5 answers)
Closed 9 years ago.
#include <stdio.h>
int main()
{
int i;
i=1;
printf("%d ",!i);
i=5;
printf("%d ",!i);
i=0;
printf("%d\n",!i);
return 0;
}
I got the following output in C: 0 0 1
What is the logic behind the output?
In C, any non zero value is considered to be a true value. So taking the logical negation with ! converts it to 0. The logical negation of 0 is 1.
In C booleans are integers where 0 is false and any other value is true.
! is NOT (as you know) so it turns any value that is not 0 into 0 and it turns 0 into 1.
What do you mean by "logic"?
The specific behavior of ! operator? It is defined by the language standard. It produces 0 for non-zero argument. And 1 for zero argument. That's the way it is defined.
The rationale behind such definition? Well, it is supposed to implement the logical-not behavior. Historically, in C language logical "false" is represented by zero integer values, while everything non-zero is interpreted as logical "true". So, that's what you observe in your experiment. When ! operator (or any other logical operator in C) has to generate a "true" result, it uses 1 to represent it, not just some arbitrary non-zero value.
i is used like a boolean value:
If i != 0, then !i == 0.
If i == 0, then !i == 1.
You are performing a Boolean operation. The '!' is NOT an inverter as one would normally think of it. If you are looking for the inverter, use the '~'.
! is a boolean operator that inverts the given input, from true to false and false to true.
True is anything that is not zero. False is zero. So, when you notted 1 or 5, you invert a true value, which prints the integer value of false, 0. Next when you invert a false value, it prints the integer value of true (default 1)
I've been reading through the Linux kernel (specifically, 2.6.11).
I came across the following definition:
#define unlikely(x) __builtin_expect(!!(x), 0)
(from linux-2.6.11/include/linux/compiler.h:61 lxr link)
What does !! accomplish? Why not just use (x)?
See also:
How does logical negation work in C?
Double Negation in C++ code.
!!(x) forces it to be either 0 or 1. 0 remains 0, but any non-zero value (which would be 'true' in a boolean context) becomes 1.
It's not so much a language syntax but a common shorthand for converting a char or int into quasi-boolean.
In C logical operations such as == && ! and so on can act on int, char etc, as there is no boolean type, however according to the standard they are guaranteed to return 0 for False and 1 for true.
So for example if you have
int x = 5;
you can force it to convert to a "boolean" type (there is no boolean type in C hence the quotes) you do
x = !x; /* !5 which gives 0 always */
x = !x; /* which gives 1 always */
!!(x) is equivalent to (x) != 0 (unless some very oddball operator overloading is going on in C++).
The fact that it's not obvious what !!(x) is doing is a probably a good reason to use (x) != 0. Unless you want to be an elite kernel hacker.
See this closed question (if it's still around) for a discussion of the merits of !! (maybe that question will be be reopened, since this question indicates that it has some value).