What's the basis of conditional statements in comparing expressions? [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have this confusion about conditional statements which may be applicable to almost all programming languages.
Like for instance this C++ code:
int main()
{
char *ptr, arr[]={'C','O','M','P','I','L','E','R','\0'};
ptr = arr;
*ptr = 'Z';
while(*ptr++)
cout << *(ptr-1);
return 0;
}
As what I have learned, a conditional statement executes only when the expression is true. So in this case, this part:
while(*ptr++)
The compiler considers all the characters being true except for the NULL. So meaning to say only NULL is false in this case? And it's alright to do this with characters?:
if('x'){do something}

while(*ptr++)
will keep going till the time ptr does not point to the end of this string which is \0 (Null Terminator) , This same statement also increments ptr to point to next value on each run, so essentially its saying while this condition is true, keep going. And the condition is while ptr still points to an element of arr;
In C++, the definition of NULL is 0, so there is only an aesthetic difference. I prefer to avoid macros, so I use 0. Another problem with NULL is that people sometimes mistakenly believe that it is different from 0 and/or not an integer. In pre-standard code, NULL was/is sometimes defined to something unsuitable and therefore had/has to be avoided. That's less common these days.
Reference
Edit:
But why is it accepting arguments like: while('x')? A letter 'x' is true?
No it doesn't mean the letter itself is true, it means that its not NULL, which is 0. Consider it like this.
while('x')
is the equivalent of saying
while('x'!=0) // so that is perfectly acceptable and understandable
Edit 2:
Here is a simpler example for you to be able to better understand
#include <iostream>
int main()
{
int x=0;
if(x)
{
cout<<"If this is shown, x was not 0.";
}
if(x==0)
{
cout<<"so does it mean x is true? no: It means your condition 'x==0' is true";
}
}

In C, any number apart from 0 is considered true. (0 is false)
If you iterate over an array with *prt++, it checks if the currect index is not zero and increases the pointer.
if ('x') is perfectly valid, but it will always be considered true.
(Remember that char internally is but an 8 bit number and 0 is used to terminate strings. In the example you provided, it is used to iterate over the "string")
And yes, NULL is also considered false (because the address the pointer points to is 0), however, in the example you provided, the pointer gets dereferenced first, so it checks at the place it points to.

It is a relic of C that anything non-zero will evaluate to a boolean true when it is tested, such as your if ('x') above. x has an integer value as it is a character of non-zero value, therefore the expression would evaluate true.
In the case of the pointer iterating over the character array, C 'strings' are always ended in '\0', null, which when the pointer gets there will be the time where the while will fail as null == 0. Not to be confused with '0' as '0' is a character and has an integer value.

Related

Order of operations for bitwise operators (a & (a=1) strange behavior)?

I was messing around with some c++ code after learning that you cannot increment booleans in the standard. I thought incrementing booleans would be useful because I like compacting functions if I can and
unsigned char b = 0; //type doesn't really matter assuming no overflow
while (...) {
if (b++) //do something
...}
is sometimes useful to have, but it would be nice to not have to worry about integer overflow. Since booleans cannot take on any value besides 0 or 1, I thought that perhaps this would work. Of course, you could just have a boolean assigned to 1 after you do your operation but that takes an extra line of code.
Anyway, I thought about how I might achieve this a different way and I came up with this.
bool b = 0;
while (...)
if (b & (b=1)) ...
This turned out to always evaluate to true, even on the first pass through. I thought - sure, its just doing the bitwise operator from right to left, except that when I swapped the order, it did the same thing.
So my question is, how is this expression being evaluated so that it simplifies to always being true?
As an aside, the way to do what I wanted is like this I guess:
bool b = 0;
while (...) if (!b && !(b=1)) //code executes every time except the first iteration
There's a way to get it to only execute once, also.
Or just do the actually readable and obvious solution.
bool b = 0;
while (...) {
if (b) {} else {b=1;}
}
This is what std::exchange is for:
if (std::exchange(b, true)) {
// b was already true
}
As mentioned, sequencing rules mean that b & (b=1) is undefined behaviour in both C and C++. You can't modify a variable and read from it "without proper separation" (e.g., as separate statements).
There is no "strange behavior" here. The & operator, in your case is a bitwise arithmetic operator. These operator are commutative, so both operand must be evaluated before computing the resulting value.
As mentioned earlier, this is considered as undefined behavior, as the standard does not prevent computing + loading into a register the left operand, before doing the same to the second, or doing so in reverse order.
If you are using C++14 or above, you could use std::exchange do achieve this, or re-implement it quite easily using the following :
bool exchange_bool(bool &var, bool &&val) {
bool ret = var;
var = val;
return ret;
}
If you end up re-implementing it, consider using template instead of hard-coded types.
As a proper answer to your question :
So my question is, how is this expression being evaluated so that it simplifies to always being true?
It does not simplify, if we strictly follow the standard, but I'd guess you are always using the same compiler, which end up producing the same output.
Side point: You should not "compact" functions. Most of the time the price of this is less readability. This might be fine if you're the only dev working on a project, but on bigger project, or if you come back to your code later, that could be an issue. Last but not least, "compact" function are more error prone, because of their lack of readability.
If you really want shorter function, you should consider using sub-function that will handle part of the function computation. This would enable you to write short function, to quickly fix or update behavior, without impacting clarity.
I don't see what meaning you can assign to a "bitwise increment" operator. If I am right, what you achieve is just setting the low-order bit, which is done by b|= 1 (following the C conventions, this could have been defined as a unary b||, but the || was assigned another purpose). But I don't feel that this is a useful bitwise operation, and it can increment only once. IMO the standard increment operator is more bitwise.
If your goal was in fact to "increment" a boolean variable, i.e. set it to true (prefix or postfix), b= b || true is a way. (There is no "logical OR assignement" b||= true, and even less a "logical increment" b||||.)

Boolean data type vs integer data types to represent truth values [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
What is advantage of using bool data type over integer values as 0 and 1 for true and false values, which will be more efficient to use?
And how it will differ in different languages like c and c++?
int was used in C when there was no bool, there is no advantage1 using an integer type to represent a boolean value in C++ or in modern C:
bool is meaningful, int is not:
bool try_something();
int try_something(); // What does this return?
It is common in C to have functioning returning int to indicate success or failure, but a lot (most?) of these do not return 1 on success and 0 on failure, they follow UNIX standard which is to return 0 in case of success and something else in case of error, so you get code like this:
int close(int fd);
if (close(fd)) { /* Something bad happened... */ }
See close manual which returns 0 on success and -1 on failure. For new user, this code is disconcerting, you expect close to return something that is true if it succeed, not the opposite.
If you need to store large amount of boolean values, you may want to optimize the storage by using only one bit to represent the value (against 32 bits if you store it in a int), and in C++, std::vector<bool>2 is already specialized to do that, so:
std::vector<bool> bvec(8000); // Size ~ 1000 bytes (optimization of std::vector<bool>)
std::vector<int> ivec(8000); // Size ~ 32000 bytes (32-bits int)
1 There are no advantages if you use them in the same way (e.g. by doing bool b = f(); vs. int b = f(); or the vector<bool> above (if you can replace int by bool without problem in your code, then do so)), but if you use an int to store multiple boolean values using bitwise operations, this is another question.
2 Note that this only applies to std::vector<bool>, other containers such as std::array<bool, N> are not optimized because they cannot use proxy object to "represent" a bit value.
It's mainly a style issue and so it's hard to prove one way is correct. C allows the syntax if(x) where the condition is executed if x is non-zero. So "true" can be a bit of a trap, if(x == true) doesn't always mean what you think. On the other hand, return true is a lot clearer than return 1 in a function like is_valid(). bool can be more memory efficient but that can be an illusion, often it's padded to four bytes anyway for efficiency reasons.
The main issue with bool, though again it is style issue, is that
mywdgt = openwidget("canvaswidget", 256, 256, true);
obviously means open or create a widget, which is a canvas, and is 256 x 256 pixels. But what is the last parameter?
mywdgt = openwidget("canvaswidget", 256, 256, ALLOW_ALPHA);
is a lot clearer. You know what the parameter is and what it does, at
a glance. So bool arguments should be avoided in function signatures,
use a define instead and say what the flag means.
bool - the built-in Boolean type. A bool can have the values true and false.
So, if you have a scenario in which a boolean type makes sense, e.g., a flag or return value to denote yes/no or success/failure, you would consider using bool.
But then if you have multiple such values, the use of an int(s) would be more appropriate. bool would not be appropriate because the values involved should be restricted to true/false.
To save memory it is highly recommended to use BOOL e.g if we are just checking condition(true or false) or some thing like that.
Bool occupies only 1 byte(generally- smallest addressable size) of memory whereas integer may take 2 or 4 bytes or more depends on compiler.
So its very much advisable to use bool instead integer to store only 1 or 0. Why to waste memory if you can do it in less memory.
And the bool can guarantee to have values only 0 or 1. So it will be appropriate for conditional statements.

Strange bool values

I have this class which has a private bool member variable call positive. I want to check to see if both my class and the number I am adding to it are both positive so I wrote the expression
positive == (n > 0) //n is of type int
But for some reason when both are positive this evaluates to false. I then did a cout on positive and it has a value of 204! I though a boolean only holds 1 or 0. That would be why this is evaluating to false but why is that and how do I fix it? I am using Visual Studio 2013.
Just to clarify it should be == because I want to know if the sign is the same. So I want it to be true if both are negative or both are positive. I think I solved the problem which was that positive in one particular test case wasn't being initialized. But still why would a bool variable even if uninitialized contain a value larger and 1?
As per the standard, getting the value of an uninitialized variable is undefined behavior.
Since the actual size of a bool can be more than one bit, a bool variable containing rubbish can even hold bad values like 254. Welcome in the C++ hell!
And since (n > 0) evaluates to 1, 254 == 1 is false.
The bug is most likely due to the fact that positive never got a meaningful value since the object that contains it come into existence.
Search for a positive = something into your code and see if it is executed at least once before you use it.
Edited after Konrad comment:
The problem is most likely due to the fact that == is implemented between int-s and not bool-s relying on a bool-to-int promotion assuming the implementation of bool use 0 for false and 1 for true (and since && and || between int-s assume 0 for false and non-zero for true, bool-to-int promotion can be an identity).
This can be seen as a "compiler unfairness", but -since in the space of integer there is one false and bilions of trues- if operator==(bool,bool) was applied, there where more chance the uninitialized bug wold have been not discovered.
Treating bool as int in the arithmetic operations (not logic ones) makes bad-bool values to come out, thus revealing the bug.
Of course, since behind it there is an UB, it's all in an implementation choice. And it is int the freedom of each reading this to think I'm try to sell a bug as a feature.
Oh, you have a == where you should have an =.
The == doesn't assign, it checks for equality
Should be
bool positive = (n > 0) //n is of type int
bool generally holds only 1 or 0 after assignment. The only reason I can imagine you would see 204 in a bool is if the variable was uninitialized (so it had a junk value).

Why does this if executes while I have not given any input?

Here is my code snippet:
int a;
if(a=8)
cout<<"Its right";
else
cout<<"Not at all";
getch();
return(0);
I'm getting the output Its right while I've not give any input there its just a assignment to the a=8.
**Borland Compiler** gives the following 2 warnings and executes the code.
1: Possible incorrect assignment (a=8)
2: 'a' is assigned a value that is never used.
When you write:
if(a=8)
You're assigning 8 to the variable a, and returning a, so you're effectively writing:
a = 8;
if(a)
This is non-zero, and hence treated as "true".
I (and the compiler) suspect you intended to write (note == instead of =):
if(a==8)
This is why you get the warnings. (Note that, in this case, a is still uninitialized, so the behavior is undefined. You will still get a warning, and may still return true...)
a = 8 assign 8 to a and returns the value of the assignment, that is 8. 8 is different from 0 and thus is considered true. the test apsses, and the program outputs "Its right".
you may have written if ( a == 8 ) which correctly tests the value of a without changing its value.
if(a=8)
implies assign a value of 8 to a and then use it to evaluate for the if statement. Since 8 is nonzero it essentially translates to TRUE (any value that is non-zero is true).
The first warning is because it's a frequent typo to write = in a condition test where you meant ==. The philosophy behind the warning is that it's a lesser burden for a programmer to rewrite if(a=b) to, say if((a=b)!=0) in the few cases he wants that, than to spend frustrating hours debugging the results if he mistakenly got an assignment instead of a comparison.
The second warning is just what it says: It looks like a mistake to have a local variable that you assign a value to but never use.
Since they are just warnings, you're free to ignore them if you think you know what you're doing. The compiler may even provide a way for you to turn them off.
Everyone else's answer is correct :)
if (a = 8) // Sets a to be 8 (and returns true so the if statement passes)
if (a == 8) // Check to see if a is equal to 8
I just want to add that I always (force of habit!) write if statements this way :
if (8 == a) {
Now, if I miss out one of the =, the compiler doesn't give me a warning, it gives me an error :)
You need a == (double equals). Single = is an assignment; when treated as an expression as you have done here, it evaluates to the value assigned, in this case 8. 0 is treated as False and anything else is True, so (a=8) == 8 == True.

Strange C++ boolean casting behaviour (true!=true)

Just read on an internal university thread:
#include <iostream>
using namespace std;
union zt
{
bool b;
int i;
};
int main()
{
zt w;
bool a,b;
a=1;
b=2;
cerr<<(bool)2<<static_cast<bool>(2)<<endl; //11
cerr<<a<<b<<(a==b)<<endl; //111
w.i=2;
int q=w.b;
cerr<<(bool)q<<q<<w.b<<((bool)((int)w.b))<<w.i<<(w.b==a)<<endl; //122220
cerr<<((w.b==a)?'T':'F')<<endl; //F
}
So a,b and w.b are all declared as bool. a is assigned 1, b is assigned 2, and the internal representation of w.b is changed to 2 (using a union).
This way all of a,b and w.b will be true, but a and w.b won't be equal, so this might mean that the universe is broken (true!=true)
I know this problem is more theoretical than practical (a sake programmer doesn't want to change the internal representation of a bool), but here are the questions:
Is this okay? (this was tested with g++ 4.3.3) I mean, should the compiler be aware that during boolean comparison any non-zero value might mean true?
Do you know any case where this corner case might become a real issue? (For example while loading binary data from a stream)
EDIT:
Three things:
bool and int have different sizes, that's okay. But what if I use char instead of int. Or when sizeof(bool)==sizeof(int)?
Please give answer to the two questions I asked if possible. I'm actually interested in answers to the second questions too, because in my honest opinion, in embedded systems (which might be 8bit systems) this might be a real problem (or not).
New question: Is this really undefined behavior? If yes, why? If not, why? Aren't there any assumptions on the boolean comparison operators in the specs?
If you read a member of a union that is a different member than the last member which was written then you get undefined behaviour. Writing an int member and then reading the union's bool member could cause anything to happen at any subsequent point in the program.
The only exception is where the unions is a union of structs and all the structs contain a common initial sequence, in which case the common sequence may be read.
Is this okay? (this was tested with g++ 4.3.3) I mean, should the compiler be aware that during boolean comparison any non-zero value might mean true?
Any integer value that is non zero (or pointer that is non NULL) represents true.
But when comparing integers and bool the bool is converted to int before comparison.
Do you know any case where this corner case might become a real issue? (For example while binary loading of data from a stream)
It is always a real issue.
Is this okay?
I don't know whether the specs specify anything about this. A compiler might always create a code like this: ((a!=0) && (b!=0)) || ((a==0) && (b==0)) when comparing two booleans, although this might decrease performance.
In my opinion this is not a bug, but an undefined behaviour. Although I think that every implementor should tell the users how boolean comparisons are made in their implementation.
If we go by your last code sample both a and b are bool and set to true by assigning 1 and 2 respectfully (Noe the 1 and 2 disappear they are now just true).
So breaking down your expression:
a!=0 // true (a converted to 1 because of auto-type conversion)
b!=0 // true (b converted to 1 because of auto-type conversion)
((a!=0) && (b!=0)) => (true && true) // true ( no conversion done)
a==0 // false (a converted to 1 because of auto-type conversion)
b==0 // false (b converted to 1 because of auto-type conversion)
((a==0) && (b==0)) => (false && false) // false ( no conversion done)
((a!=0) && (b!=0)) || ((a==0) && (b==0)) => (true || false) => true
So I would always expect the above expression to be well defined and always true.
But I am not sure how this applies to your original question. When assigning an integer to a bool the integer is converted to bool (as described several times). The actual representation of true is not defined by the standard and could be any bit pattern that fits in an bool (You may not assume any particular bit pattern).
When comparing the bool to int the bool is converted into an int first then compared.
Any real-world case
The only thing that pops in my mind, if someone reads binary data from a file into a struct, that have bool members. The problem might rise, if the file was made with an other program that has written 2 instead of 1 into the place of the bool (maybe because it was written in another programming language).
But this might mean bad programming practice.
Writing data in a binary format is non portable without knowledge.
There are problems with the size of each object.
There are problems with representation:
Integers (have endianess)
Float (Representation undefined ((usually depends on the underlying hardware))
Bool (Binary representation is undefined by the standard)
Struct (Padding between members may differ)
With all these you need to know the underlying hardware and the compiler. Different compilers or different versions of the compiler or even a compiler with different optimization flags may have different behaviors for all the above.
The problem with Union
struct X
{
int a;
bool b;
};
As people mention writing to 'a' and then reading from 'b' is undefined.
Why: because we do not know how 'a' or 'b' is represented on this hardware. Writing to 'a' will fill out the bits in 'a' but how does that reflect on the bits in 'b'. If your system used 1 byte bool and 4 byte int with lowest byte in low memory highest byte in the high memory then writing 1 to 'a' will put 1 in 'b'. But then how does your implementation represent a bool? Is true represented by 1 or 255? What happens if you put a 1 in 'b' and for all other uses of true it is using 255?
So unless you understand both your hardware and your compiler the behavior will be unexpected.
Thus these uses are undefined but not disallowed by the standard. The reason they are allowed is that you may have done the research and found that on your system with this particular compiler you can do some freeky optimization by making these assumptions. But be warned any changes in the assumptions will break your code.
Also when comparing two types the compiler will do some auto-conversions before comparison, remember the two types are converted into the same type before comparison. For comparison between integers and bool the bool is converted into an integer and then compared against the other integer (the conversion converts false to 0 and true to 1). If the objects being converted are both bool then no conversion is required and the comparison is done using boolean logic.
Normally, when assigning an arbitrary value to a bool the compiler will convert it for you:
int x = 5;
bool z = x; // automatic conversion here
The equivalent code generated by the compiler will look more like:
bool z = (x != 0) ? true : false;
However, the compiler will only do this conversion once. It would be unreasonable for it to assume that any nonzero bit pattern in a bool variable is equivalent to true, especially for doing logical operations like and. The resulting assembly code would be unwieldy.
Suffice to say that if you're using union data structures, you know what you're doing and you have the ability to confuse the compiler.
The boolean is one byte, and the integer is four bytes. When you assign 2 to the integer, the fourth byte has a value of 2, but the first byte has a value of 0. If you read the boolean out of the union, it's going to grab the first byte.
Edit: D'oh. As Oleg Zhylin points out, this only applies to a big-endian CPU. Thanks for the correction.
I believe what you're doing is called type punning:
http://en.wikipedia.org/wiki/Type_punning
Hmm strange, I am getting different output from codepad:
11
111
122222
T
The code also seems right to me, maybe it's a compiler bug?
See here
Just to write down my points of view:
Is this okay?
I don't know whether the specs specify anything about this. A compiler might always create a code like this: ((a!=0) && (b!=0)) || ((a==0) && (b==0)) when comparing two booleans, although this might decrease performance.
In my opinion this is not a bug, but an undefined behaviour. Although I think that every implementor should tell the users how boolean comparisons are made in their implementation.
Any real-world case
The only thing that pops in my mind, if someone reads binary data from a file into a struct, that have bool members. The problem might rise, if the file was made with an other program that has written 2 instead of 1 into the place of the bool (maybe because it was written in another programming language).
But this might mean bad programming practice.
One more: in embedded systems this bug might be a bigger problem, than on a "normal" system, because the programmers usually do more "bit-magic" to get the job done.
Addressing the questions posed, I think the behavior is ok and shouldn't be a problem in real world. As we don't have ^^ in C++ I would suggest !bool == !bool as a safe bool comparison technique.
This way every non-zero value in bool variable will be converted to zero and every zero is converted to some non-zero value, but most probably one and the same for any negation operation.