While perusing through my organization's source repository I came across this little gem:
RawParameterStorage[!ParameterWorkingIdx][ParameterDataOffset] = ...
Is this valid code? (It compiles) What does the exclamation mark here do?
An invert ~ operator might make sense, since it's commonly confused with the not ! operator in boolean expressions. However, it doesn't seem to make logical sense to impose the not ! operator on an array index. Any Thoughts?
!ParameterWorkingIdx Means ParameterWorkingIdx is 0, If it is, !ParameterWorkingIdx evaluates as true which might be implicitly converted to the indexer type (For example, 1 for integer indexer as in an array), otherwise, it evaluates as false.
If ParameterWorkingIdx == 0 then [!ParameterWorkingIdx] == [1].
If ParameterWorkingIdx != 0 then [!ParameterWorkingIdx] == [0].
It also depends on other stuff like:
The type of ParameterWorkingIdx.
overloading of ! operator by the type of ParameterWorkingIdx.
indexer overloading by the type of RawParameterStorage.
etc...
Taking a bit of a guess here, but that looks like a double-buffer pattern. ParameterWorkingIdx would flip-flop between 0 and 1 (probably with ParameterWorkingIdx = !ParameterWorkingIdx;).
Then, at any time, RawParameterStorage[ParameterWorkingIdx] would be the current buffer, and RawParameterStorage[!ParameterWorkingIdx] would be the previous buffer.
it doesn't seem to make logical sense to impose the not ! operator on an array index
It might: all it does here is convert zero to one, and any other number to zero.
We can infer from this code that RawParameterStorage probably has two elements at the top level.
P. S. Here, I assume that RawParameterStorage is an array (as you say it is). Furthermore, I assume that ParameterWorkingIdx is an integer (as its name implies). If, for example, either is a class with overloaded operators than the semantics could be completely different.
Is this valid code?
Yes it is. Suppose ParameterWorkingIdx to be an int, for !ParameterWorkingIdx, when used with operators !, it'll be contextually convertible to bool,
The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false. All other values become true.
Then integral promoted to be used as the array index.
the type bool can be converted to int with the value false becoming 0 and true becoming 1.
So !ParameterWorkingIdx is equivalent with ParameterWorkingIdx == 0 ? 1 : 0, which is much more clear IMO.
Related
Recently my friend showed me an article that showed +!!"" is == to 1 in C++...
What subject does this fall under ? Where can I look into it ? Why is this true ? I can't find information about this anywhere
What subject does this fall under ?
Implicit conversions. And operators. And string literals. All of which are subtopics of expressions.
Where can I look into it ?
The c++ standard is the authoritative specification. There are also unofficial websites that describe the rules.
Why is this true ?
"" is a(n empty) string literal. String literals are arrays (of characters). Arrays decay to pointer to first element. The logical NOT operator (!) evaluates to false when the operand is a non null pointer. The NOT operator evaluates to true when the operand is false. The unary plus arithmetic operator implicitly converts the operand to integer. True is converted to 1.
”” is an array of const char. In most contexts, an array decays into a pointer to its first element. That’s what happens here. When you apply ! to a pointer, the result is true if the pointer is a null pointer, otherwise it’s false. The pointer is not a null pointer, so !”” has the value false. !false is true, so !!”” is true. Unary + promotes smaller types to int; in this case, it promotes the value true from bool to int. When true is promoted to int it becomes 1.
Context
While I was reading Consistent comparison, I have noticed a peculiar usage of the verb to compare:
There’s a new three-way comparison operator, <=>. The expression a <=> b
returns an object that compares <0 if a < b, compares >0 if a > b, and
compares ==0 if a and b are equal/equivalent.
Another example found on the internet (emphasis mine):
It returns a value that compares less than zero on failure. Otherwise,
the returned value can be used as the first argument on a later call
to get.
One last example, found in a on GitHub (emphasis mine):
// Perform a circular 16 bit compare.
// If the distance between the two numbers is larger than 32767,
// and the numbers are larger than 32768, subtract 65536
// Thus, 65535 compares less than 0, but greater than 65534
// This handles the 65535->0 wrap around case correctly
Of course, for experienced programmers the meaning is clear. But the way the verb to compare is used in these examples is not standard in any standardized forms of English.
Questions*
How does the programming jargon sentence "The object compares less than zero" translate into plain English?
Does it mean that if the object is compared with0 the result will be "less than zero"?
Why would be wrong to say "object is less than zero" instead of "object compares less than zero"?
* I asked for help on English Language Learners and English Language & Usage.
"compares <0" in plain English is "compares less than zero".
This is a common shorthand, I believe.
So to apply this onto the entire sentence gives:
The expression a <=> b returns an object that compares less than zero
if a is less than b, compares greater than zero if a is greater than
b, and compares equal to zero if a and b are equal/equivalent.
Which is quite a mouthful. I can see why the authors would choose to use symbols.
What I am interested in, more exactly, is an equivalent expression of "compares <0". Does "compares <0" mean "evaluates to a negative number"?
First, we need to understand the difference between what you quoted and actual wording for the standard. What you quoted was just an explanation for what would actually get put into the standard.
The standard wording in P0515 for the language feature operator<=> is that it returns one of 5 possible types. Those types are defined by the library wording in P0768.
Those types are not integers. Or even enumerations. They are class types. Which means they have exactly and only the operations that the library defines for them. And the library wording is very specific about them:
The comparison category types’ relational and equality friend functions are specified with an anonymous parameter of unspecified type. This type shall be selected by the implementation such that these parameters can accept literal 0
as a corresponding argument. [Example: nullptr_t satisfies this requirement. —
end example] In this context, the behaviour of a program that supplies an argument other than a literal 0 is undefined.
Therefore, Herb's text is translated directly into standard wording: it compares less than 0. No more, no less. Not "is a negative number"; it's a value type where the only thing you can do with it is comparing it to zero.
It's important to note how Herb's descriptive text "compares less than 0" translates to the actual standard text. The standard text in P0515 makes it clear that the result of 1 <=> 2 is strong_order::less. And the standard text in P0768 tells us that strong_order::less < 0 is true.
But it also tells us that all other comparisons are the functional equivalent of the descriptive phrase "compares less than 0".
For example, if -1 "compares less than 0", then that would also imply that it does not compare equal to zero. And that it does not compare greater than 0. It also implies that 0 does not compare less than -1. And so on.
P0768 tells us that the relationship between strong_order::less and the literal 0 fits all of the implications of the words "compares less than 0".
"acompares less than zero" means that a < 0 is true.
"a compares == 0 means that a == 0 is true.
The other expressions I'm sure make sense now right?
Yes, an "object compares less than 0" means that object < 0 will yield true. Likewise, compares equal to 0 means object == 0 will yield true, and compares greater than 0 means object > 0 will yield true.
As to why he doesn't use the phrase "is less than 0", I'd guess it's to emphasize that this is all that's guaranteed. For example, this could be essentially any arbitrary type, including one that doesn't really represent an actual value, but instead only supports comparison with 0.
Just, for example, let's consider a type something like this:
class comparison_result {
enum { LT, GT, EQ } res;
friend template <class Integer>
bool operator<(comparison_result c, Integer) { return c.res == LT; }
friend template <class Integer>
bool operator<(Integer, comparison_result c) { return c.res == GT; }
// and similarly for `>` and `==`
};
[For the moment, let's assume the friend template<...> stuff is all legit--I think you get the basic idea, anyway).
This doesn't really represent a value at all. It just represents the result of "if compared to 0, should the result be less than, equal to, or greater than". As such, it's not that it is less than 0, only that it produces true or false when compared to 0 (but produces the same results when compared to another value).
As to whether <0 being true means that >0 and ==0 must be false (and vice versa): there is no such restriction on the return type for the operator itself. The language doesn't even include a way to specify or enforce such a requirement. There's nothing in the spec to prevent them from all returning true. Returning true for all the comparisons is possible and seems to be allowed, but it's probably pretty far-fetched.
Returning false for all of them is entirely reasonable though--just, for example, any and all comparisons with floating point NaNs should normally return false. NaN means "Not a Number", and something that's not a number isn't less than, equal to or greater than a number. The two are incomparable, so in every case, the answer is (quite rightly) false.
I think the other answers so far have answered mostly what the result of the operation is, and that should be clear by now. #VTT's answer explains it best, IMO.
However, so far none have answered the English language behind it.
"The object compares less than zero." is simply not standard English, at best it is jargon or slang. Which makes it all the more confusing for non-native speakers.
An equivalent would be:
A comparison of the object using <0 (less than zero) always returns true.
That's quite lengthy, so I can understand why a "shortcut" was created:
The object compares less than zero.
It means that the expression will return an object that can be compared to <0 or >0 or ==0.
If a and b are integers, then the expression evaluates to a negative value (probably -1) if a is less than b.
The expression evaluates to 0 if a==b
And the expression will evaluates to a positive value (probably 1) if a is greater than b.
In c++, bool is used to represent Boolean. that is it holds true or false. But in some case we can use bool to represent integers also.
what is the meaning of bool a=5; in c++?
"what is the meaning of bool a=5; in c++?"
It's actually equivalent to writing
bool a = (5 != 0);
"But in some case we can use bool to represent integers also."
Not really. The bool value only represents whether the integer used to initialize it was zero (-> false) or not (-> true).
The other way round (as mentioned in #Daniel Frey's comment) false will be converted back to an integer 0, and true will become 1.
So the original integer value's (or any other expression results like pointers, besides nullptr, or double values not exactly representing 0.0) will be lost.
Conclusion
As mentioned in LRiO's answer, it's not possible to store information other than false or true in a bool variable.
There are guaranteed rules of conversion though (citation from cppreference.com):
The safe bool problem
Until the introduction of explicit conversion functions in C++11, designing a class that should be usable in boolean contexts (e.g. if(obj) { ... }) presented a problem: given a user-defined conversion function, such as T::operator bool() const;, the implicit conversion sequence allowed one additional standard conversion sequence after that function call, which means the resultant bool could be converted to int, allowing such code as obj << 1; or int i = obj;.
One early solution for this can be seen in std::basic_ios, which defines operator! and operator void* (until C++11), so that the code such as if(std::cin) {...} compiles because void* is convertible to bool, but int n = std::cout; does not compile because void* is not convertible to int. This still allows nonsense code such as delete std::cout; to compile, and many pre-C++11 third party libraries were designed with a more elaborate solution, known as the Safe Bool idiom.
No, we can't.
It's just that there's an implicit conversion from integer to boolean.
Zero becomes false; anything else becomes true.
In fact this declaration
bool a=5;
is equivalent to
bool a=true;
except that in the first declaration 5 as it is not equal to zero is implicitly converted to true.
From the C++ Standard (4.12 Boolean conversions )
1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer
to member type can be converted to a prvalue of type bool. A zero
value, null pointer value, or null member pointer value is converted
to false; any other value is converted to true. For
direct-initialization (8.5), a prvalue of type std::nullptr_t can be
converted to a prvalue of type bool; the resulting value is false.
One more funny example
bool a = new int;
Of course it does not mean that we may use bool to represent pointers. Simply if the allocation is successfull then the returned poimter is not equal to zero and implicitly converted to true according to the quote I showed.
Take into account that till now some compilers have a bug and compile this code successfully
bool a = nullptr;
Though according to the same quote a valid declaration will look like
bool a( nullptr );
And, basically, I would opine that bool b=5 is "just plain wrong."
Both C and C++ have a comparatively weak system of typing. Nevertheless, I'm of the opinion that this should have produced a compile error ... and, if not, certainly a rejected code review, because it is (IMHO) more likely to be an unintentional mistake, than to be intention.
You should examine the code to determine whether b is or is not "really" being treated as a bool value. Barring some "magic bit-twiddling purpose" (which C/C++ programs sometimes are called-upon to do ...), this is probably a typo or a bug.
Vlad's response (below) shows what the standard says will happen if you do this, but I suggest that, "since it does not make human-sense to do this, it's probably an error and should be treated accordingly by the team.
A "(typecast)?" Maybe. A data-type mismatch such as this? Nyet.
I have an expression which returns 0 or 1 integer as a temporary value. The value is probably already in a register and I would like to return it as a bool from an inlined function.
Is there an ordinary way to do this? I believe (bool) and static_cast<bool> inject additional test and set instructions. And this is too much for me, while the case is about a performance critical part of memory manager.
Just return it. Any value, different from 0 is true and 0 is false in c++.
Just return the int from your inline function (which returns bool).
Assuming your integer expression is foo, then use !!foo to get the bool value.
What are you doing with the return value? If you are using it
immediately in condition, the compiler will probably generate
exactly the same code, regardless of whether the type is bool
or not. There will be a simple comparison with 0. If you are
assigning it to a bool variable, the compiler will generally
generate an extra instruction, to ensure that the binary value
is either 0 or 1 (and not some other value). But what is
the expression, so that you can be sure that it is either 0 or
1? If it is something like x & 1, a good compiler will
recognize this, and will optimize out the extra instruction.
EDIT:
I might add that I am assuming inlining and optimization.
If performance is an issue, those are the first two steps
you should take.
When I come across such performance warnings in cppcheck, I usually use the most elegant approach for this (at least in my opinion ;) ):
return yourInt != 0;
This sticks with the assumption that all values different from 0 are considered true.
how about
return rtVal;
just return the integer will return true if it isn't 0
from c++ 2012 standard (ISO/IEC N3337):
4.12 Boolean conversions
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a
prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false;
any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of
type bool; the resulting value is false.
So just return it?!
In a book I am reading there is a piece of code :
string x;
size_t h=0;
for(const char* s=x.c_str();*s;++s)
h=(h*17)^*s;
Regarding this code, I have two questions:
how can *s be a condition? what does it mean?
what does "h=(h*17)^*s" mean?
Thanks for help!
how can *s be a condition? what does it mean?
It means "while the value pointed to by s is not zero." C strings are null-terminated, so the last character in the string returned by c_str() will be the null character (\0, represented by all bits zero).
what does "h=(h*17)^*s" mean?
It multiplies h by 17 then xors it with the value pointed to by s.
In C (or C++) any value can be used as a "boolean". A numeric value of 0, or a NULL pointer, means "false". Anything else means "true".
Here, *s is "the character value currently pointed to by s". The loop stops if that character is a 0 (not the "0" digit, with ASCII encoding 48, but the byte with ASCII encoding 0). This is conventionally the "end-of-string" marker, so the loop stops when it reaches the end of the string.
"^" is the bitwise XOR operator. The left "*" is a plain multiplication, while the other "*" is the pointer dereference operator (i.e. the thing which takes the pointer s and looks at the value to which this pointer points). "=" is assignment. In brief, the value of h is multiplied by 17, then XORed with the character pointed to by s, and the result becomes the new value of h.
*s detects the string termination character '\0'
(h*17)^*s is what it says: h multiplied by 17 and xor-ed with the content of the character pointed by s. Seems a simple hashing funciton.
As other answers have explained, the basic answer is that any expression that evaluates to 0 gets interpreted as a 'false' condition in C or C++, and *s will evaluate to 0 when the s pointer reaches the null termination character of the string ('\0').
You could equivalently use the expression *s != 0, and some developers might argue that this is what should be used, giving the opinion that the 'fuller' expression is more clear. Whether or not you agree with that opinion, you need to be able to understand the use of the terse alternative, since it's very commonly used in C/C++ code. You'll come across these expressions a lot, even if you prefer to use the more explicit comparision.
The more rigorous explanation from the standard (for some reason I feel compelled to bring this into the discussion, even though it doesn't really change or clarify anything. In fact, it probably will muddle things unnecessarily for some people - if you don't care to get into this level of trivia, you'll miss absolutely nothing by clicking the back button right now...):
In C, the *s expression is in what the standard calls 'expression-2' of the for statement, and this particular for statement example is just taking advantage of the standard's definition of the for statement. The for statement is classified as an 'iteration statement', and among the semantics of any iteration statement are (6.8.5/4 "Iteration statements"):
An iteration statement causes a statement called the loop body to be executed repeatedly
until the controlling expression compares equal to 0.
Since the 'expression-2' part of the for statement is the controlling expression, this means that the for loop will execute repeatedly until *s compares equal to 0.
The C++ standard defines things a little differently (but with the same result). In C++, the for statement is defined in terms of the while statement, and the condition part of the while statement controls the the iteration (6.5.1/1 "The while statement"):
until the value of the condition becomes false
Earlier in the C++ standard, the following describes how expressions are converted to bool (4.12 "boolean conversions"):
An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true
Similar wording in the standard (in both languages) apply to the controlling expression/condition of all selection or iteration statements. All this language-lawyerese boils down to the fact that if an expression evaluates to 0 it's the same as evaluating to false (in the English sense of the word, since C doesn't have a built-in false keyword).
And that's the long, confusing explanation of the simple concept.
*s is the character that s currently points to, so it's a character. The for loop goes on until it becomes \0, meaning until the string ends.
h is assigned the value of h * 17 xored with the (ascii value of) character *s.
Here's a good tutorial about pointers.
1) *s in the condition checks whether *s!=NUL
2) h=(h*17)^*s implies multiply h by 17 and perform exclusive-OR operation with the value pointed to by s.
In C and C++, true and false are the same as non-zero, and zero. So code under if (1){ will always execute, as will code under if (-1237830){, but if (0){ is always false.
Likewise, if the value of the pointer is ever 0, the condition is the same as false, i.e. you will exit the loop.