Can someone tell me why this doesn't work? (SOLVED)

New to FreeBASIC? Post your questions here.
Rev5
Posts: 26
Joined: Jun 04, 2014 22:28
Location: USA

Can someone tell me why this doesn't work? (SOLVED)

In the code below why do unsigned variables not return as expected :

Code: Select all

# DEFINE FALSE 0
# DEFINE TRUE ( NOT FALSE )

DECLARE FUNCTION CHECK_UBYTE() AS UBYTE
DECLARE FUNCTION CHECK_BYTE() AS BYTE

DIM AS UBYTE UB = TRUE
DIM AS BYTE B = TRUE

IF CHECK_UBYTE() = TRUE THEN
PRINT "CHECK_UBYTE() = TRUE"
ELSE
PRINT "CHECK_UBYTE() = FALSE"
END IF
IF CHECK_BYTE() = TRUE THEN
PRINT "CHECK_BYTE() = TRUE"
ELSE
PRINT "CHECK_BYTE() = FALSE"
END IF
IF UB = TRUE THEN
PRINT "UB = TRUE"
ELSE
PRINT "UB = FALSE"
END IF
IF UB = CAST( UBYTE, TRUE ) THEN
PRINT "UB = TRUE IF CAST( UBYTE, _ )
ELSE
PRINT "UB <> TRUE IF CAST( UBYTE, _ )
END IF
IF B = TRUE THEN
PRINT "B = TRUE"
ELSE
PRINT "B = FALSE"
END IF
SLEEP

FUNCTION CHECK_UBYTE() AS UBYTE
'RETURN FALSE
RETURN TRUE
END FUNCTION

FUNCTION CHECK_BYTE() AS BYTE
'RETURN FALSE
RETURN TRUE
END FUNCTION
Last edited by Rev5 on Jul 17, 2014 4:12, edited 1 time in total.
Rev5
Posts: 26
Joined: Jun 04, 2014 22:28
Location: USA

Re: Can someone tell me why this doesn't work?

I thought on a binary level that TRUE would be all 1s since FALSE is all 0s. I updated the first link with further checks including variables and not just function returns. I also did a check using Cast() that does work as expected. I'm still misunderstanding how unsigned variables work on a binary level in comparison to signed variables.
vdecampo
Posts: 2982
Joined: Aug 07, 2007 23:20
Location: Maryland, USA
Contact:

Re: Can someone tell me why this doesn't work?

NOT FALSE = -1

This is why unsigned is not working. You can define FALSE as zero and TRUE as anything else (positive if you want it to work with unsigned numbers).

-Vince
Rev5
Posts: 26
Joined: Jun 04, 2014 22:28
Location: USA

Re: Can someone tell me why this doesn't work?

I'm still missing something... If false = 0 then all of its bits are zeroes, right? So doesn't true ( not false ) mean all of its bits are ones? Are unsigned variable bits handled differently than signed variable bits?
Rev5
Posts: 26
Joined: Jun 04, 2014 22:28
Location: USA

Re: Can someone tell me why this doesn't work?

After digging through the manual I discovered the Bin() function and found out that my #define FALSE and TRUE are both 32 bits in length. After switching from the 8 bit Bytes to 32 bit Integers I had no problems. Better yet for this scenario both signed and unsigned Integers work.

Code: Select all

# DEFINE FALSE 0
# DEFINE TRUE ( NOT FALSE )

DECLARE FUNCTION CHECK_UINTEGER() AS UINTEGER
DECLARE FUNCTION CHECK_INTEGER() AS INTEGER

DIM AS UINTEGER UI = TRUE
DIM AS INTEGER I = TRUE

IF CHECK_UINTEGER() = TRUE THEN
PRINT "CHECK_UINTEGER() = TRUE"
ELSE
PRINT "CHECK_UINTEGER() = FALSE"
END IF
IF CHECK_INTEGER() = TRUE THEN
PRINT "CHECK_INTEGER() = TRUE"
ELSE
PRINT "CHECK_INTEGER() = FALSE"
END IF
IF UI = TRUE THEN
PRINT "UI = TRUE"
ELSE
PRINT "UI = FALSE"
END IF
IF UI = CAST( UINTEGER, TRUE ) THEN
PRINT "UI = TRUE IF CAST( UINTEGER, _ )"
ELSE
PRINT "UI <> TRUE IF CAST( UINTEGER, _ )"
END IF
IF I = TRUE THEN
PRINT "I = TRUE"
ELSE
PRINT "I = FALSE"
END IF
SLEEP

FUNCTION CHECK_UINTEGER() AS UINTEGER
'RETURN FALSE
RETURN TRUE
END FUNCTION

FUNCTION CHECK_INTEGER() AS INTEGER
'RETURN FALSE
RETURN TRUE
END FUNCTION
codeFoil
Posts: 255
Joined: Dec 22, 2011 4:45
Location: United States
Contact:

Re: Can someone tell me why this doesn't work?

Code: Select all

Print Len(TRUE)

You'll find that the expression you've defined (NOT TRUE) is being evaluated as a 4 byte Integer.
When you cast -1 to a UBYTE, you do indeed have all 8 bits set, which equals 255, but you are comparing it to a 32 bit signed value with all bits set. That is definitely not equal to 255. Since you are comparing an Integer with a byte, the byte value must be coerced to an Integer, so your Boolean expression is equivalent to 255 = -1 which is never true.

Replace

Code: Select all

#DEFINE TRUE (NOT FALSE)

with

Code: Select all

CONST AS UBYTE TRUE = (NOT FALSE)

and you will see different results.

Rev5
Posts: 26
Joined: Jun 04, 2014 22:28
Location: USA

Re: Can someone tell me why this doesn't work? (SOLVED)

Thanks for taking the time to explain this. Now I know about Len() too. I don't use #define often but from the numerous examples of various code I've read through I've seen TRUE and FALSE almost always assigned that way.
counting_pine
Posts: 6225
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Can someone tell me why this doesn't work? (SOLVED)

The main thing I would take away from this problem is: because 0 is uniquely false and all nonzero values are true, you should test for truth not by comparing against any True value, but against False (i.e. 0).
Also, if you are going to use Not, make sure your value is either 0 or -1.
Even 2^32-1 is not good enough, because it assumes 32-bit Integers. But any signed type can store -1, even bytes.

(A safer 'Not' is just to test for 'n=0'. This avoids signedness problems, and is closer in effect to C's '!'.)
Rev5
Posts: 26
Joined: Jun 04, 2014 22:28
Location: USA

Re: Can someone tell me why this doesn't work? (SOLVED)

I know this thread has been solved more than a few times already, but I wanted to put this out there as well. Going back to my original problem of comparing variables of different bit size I applied the And operator in place of the Equals operator. This method works as well and below is the original code modified to work this way.

Code: Select all

# DEFINE FALSE 0
# DEFINE TRUE ( NOT FALSE )

DECLARE FUNCTION CHECK_UBYTE() AS UBYTE
DECLARE FUNCTION CHECK_BYTE() AS BYTE

DIM AS UBYTE UB = TRUE
DIM AS BYTE B = TRUE

IF CHECK_UBYTE() AND TRUE THEN
PRINT "CHECK_UBYTE() = TRUE"
ELSE
PRINT "CHECK_UBYTE() = FALSE"
END IF
IF CHECK_BYTE() AND TRUE THEN
PRINT "CHECK_BYTE() = TRUE"
ELSE
PRINT "CHECK_BYTE() = FALSE"
END IF
IF UB AND TRUE THEN
PRINT "UB = TRUE"
ELSE
PRINT "UB = FALSE"
END IF
IF UB AND CAST( UBYTE, TRUE ) THEN
PRINT "UB = TRUE IF CAST( UBYTE, _ )"
ELSE
PRINT "UB <> TRUE IF CAST( UBYTE, _ )"
END IF
IF B AND TRUE THEN
PRINT "B = TRUE"
ELSE
PRINT "B = FALSE"
END IF
SLEEP

FUNCTION CHECK_UBYTE() AS UBYTE
'RETURN FALSE
RETURN TRUE
END FUNCTION

FUNCTION CHECK_BYTE() AS BYTE
'RETURN FALSE
RETURN TRUE
END FUNCTION
counting_pine
Posts: 6225
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Can someone tell me why this doesn't work? (SOLVED)

There's no need to do 'AND TRUE' - instead you could just write e.g. 'IF B THEN'. I personally don't find it helps readability, but it's worth a mention. IF will treat any nonzero value as true.

Something like 'B AND -1', apart from potentially changing the type of B, will have no effect on its value. In fact the AND operation will be detected by the compiler and optimised out by the compiler, much like 'OR 0,' '* 1', '+ 0', etc.
Rev5
Posts: 26
Joined: Jun 04, 2014 22:28
Location: USA

Re: Can someone tell me why this doesn't work? (SOLVED)

counting_pine wrote:In fact the AND operation will be detected by the compiler and optimised out by the compiler, much like 'OR 0,' '* 1', '+ 0', etc.

It took me a couple times reading this sentence for it to make sense. Thanks for bringing this information about the compiler to my attention :)
codeFoil
Posts: 255
Joined: Dec 22, 2011 4:45
Location: United States
Contact:

Re: Can someone tell me why this doesn't work? (SOLVED)

Rev5 wrote:Now I know about Len() too.

I should point out that is would have been wise of me to use SizeOf() rather than Len().
SizeOf will return the memory size of the data type of an expression.
Len will return the same, unless the data type is a String, in which case it returns a character count.
Rev5
Posts: 26
Joined: Jun 04, 2014 22:28
Location: USA

Re: Can someone tell me why this doesn't work? (SOLVED)

Ahh, string datatypes... That's a can of worms I haven't yet overwhelmed myself with :)