In this C++ compiler, true doesn't have a boolean value.

Go To Last Post
26 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I use the avr-gcc compiler to compile C++ code.

I'm perplexed by true. I assume it's a keyword. I also assume that bool is a built-in type. Am I wrong?

Objects of type bool can have two values, true and false. Right?

But it seems that bools that are true have a value of 0x0001, and true has a value of 0xffff. So "true" doesn't have a boolean value and isn't equal to a bool that is true!!!

For instance if we have this line:
bool george = true;

then the expression:
(george == true)

is always false. This doesn't make sense to me. I realize that it might be better to use:
if(george)

than to use :
if(george == true)

but I would expect either to work, but the second way doesn't work.
Shouldn't the keyword true have a value that is boolean, that is shouldn't it have a value of 1, instead of 0xffff?

By the way, it seems that the size of a bool on most compilers these days is usually one, the same as the size of a char. Why the heck is the size of a bool on this machine two?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
steve17 wrote:
I use the avr-gcc compiler to compile C++ code.

I'm perplexed by true. I assume it's a keyword. I also assume that bool is a built-in type. Am I wrong?

Objects of type bool can have two values, true and false. Right?

See? Now you're assuming things. :)

I don't know for C++; I don't program in that language. For that, you'll have to go get a good C++ reference and see what it says.

However, for C, you have to include to get the bool type and the allowable values are true and false.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using C as well but I defined it differently:

typedef enum { false = 0, true } bool;
#define FALSE 0
#define TRUE  1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, that's the way we used to do it in C.

But C++ has this new-fangled bool type. I've been using it for a few years with other C++ compilers. As it's relatively new, I don't expect it to be present in all C++ compilers. If it's present though, I would expect it to work.

This compiler and myself don't see eye-to-eye on this. One of us is confused.

I was wrong on one thing. The size of a bool is one. I apologize for saying it was two.

I guess I will try to get some advice from gcc.gnu.org.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simply don't make nonsensical tests like

if (boolvar == true) ...

Instead just remember that the condition of an `if' statement already
expects a boolean expression, and write

if (boolvar) ...

so it'll do the expected thing.

Nobody ever said a `bool' variable could *only* assume (the predefined
values of) true and false as valid values. This would require a 1-bit
variable which is not natively supported by almost any of our current
hardware. The usual rule of thumb (and I'm pretty sure that is
written somewhere in the standard, too) then is that any non-zero
value of such a variable will be interpreted as `true', so there's
more than one possible value for a Boolean true result. In effect,
the expression boolvar == true doesn't make much sense since it is
only testing for one specific (out of many possible) values for the
value `true'. (Incidentally, boolvar == false would always do the
expected thing, which is a cumbersome form of writing !boolvar, since
there is only one valid value for Boolean false.)

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

We both see nonsense but we see it in different places.

Actually this construct comes from the source code for the program that comes in the Atmel Butterfly. It's written in C and uses BOOL and TRUE. Apparently BOOL and TRUE are defined in a header file. When I ported it to C++ I changed BOOL to bool and TRUE to true. Then I spent hours figuring out why it didn't work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Finding it in Atmel's sources doesn't make it anything better than
nonsense. ;-)

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm afraid that I do not see nonsense.

If a variable is a "bool" then it should only ever get assigned the value "true" or "false" by the compiler.

Observe the following code fragment:

bool george ;

george = 7 ;

if (george)
  {
  printf("True 1\n") ;
  }

if (george == true)
  {
  printf("True 2\n") ;
  }

printf("Numeric value = %d\n", george) ;

Running this through Borland C++ produces the following output, correct in my view.

True 1
True 2
Numeric value = 1

If the compiler is putting something other than a true or a false in the variable, then that's a compiler flaw in my view.

It's not going to stop me using it though, and it's well worth the money I paid for it. :D

And I should add that I would use:

if (george)

to make the code more robust. I just don't see it as nonsense.

Cheers
A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you try to compile the same code in C not C++?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, but I would expect the C code to behave differently (apparently "incorrectly") as having set "george" to 7 (and C not knowing about booleans) then I would expect the

(george == true)

clause to fail.

In fact, if you try (not very) hard you can screw up the C++ code with casting anyway. :)

Cheers
A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The compiler will never assign anything else but 0 (false) and 1
(true). That doesn't prevent any user program from assigning
different values though.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Agreed.

There are lots of adjectives I could apply to the coding style:

if (george == true)

including "poor", "fragile" and "crap".

I just thought your "nonsense" description was a little harsh.

And I was under the impression that the OP had ended up with a value other than 0 or 1 following straight C++ assignment. I'll go back and have another read. :)

Cheers
A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include 

#define FALSE 0
#define TRUE  1

typedef enum { false = FALSE, true } bool;

bool george;

int main ( void ) {
  george = ( bool )7;

  if ( george )         printf ( "True 1\n" );
  if ( george == true ) printf ( "True 2\n" );

  printf ( "Numeric value = %d\n", george );
  return george;
}

I tried this code with tc 2.0 (1988) and bc 3.1 ( 1991)
no warrnings, no true 2 george is always 7...
Looks liike I'm missing something :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think that what you are missing is that enums are not particularly cleverly handled either in C or C++.

Your casting of george using (bool) isn't doing anything. I don't think that casting using an enum ever has any effect. Waits to have folly of ways explained by many. :)

My original example was intended to point out that the line

george = 7 ;

has a different effect in C++ (where bool IS understood) and C (where bool is NOT understood, even if you have an enum typedef).

In C++ george gets set to 1 (true) whereas in C it gets set to 7 because george is just a byte.

I hope that helps.
/Andy

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I should get at least warrning! I don't think that compiler is right.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It depends what you mean by "should". :)

I agree that if you declare something as a particular enum, then it would be entirely reasonable to expect some kind of warning or error if you try to assign something to it that is not a valid value.

Entirely reasonable, but not part of C, or indeed C++, unfortunately.

I suppose that the runtime checking would make the final code so slow as to be unusable.

So if you need it, you've got to write it for yourself.

Cheers
A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the replies, guys. I also got some info by posting on the
gcc-help@gcc.gnu.org mailing list. They thought it appeared to be a bug. However GCC 3.4.2 on Debian worked okay.

I have subsequently found it works okay on Fedora with GCC 3.3.2.
I also found that the bug is there with AVR-GCC 3.4.2.

So it seems that this is a bug in the AVR port of GCC Where would I report this bug? Would it be the gcc.gnu.org or is there some other place that ports GCC to AVR?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can't seem to reproduce your bug. The following code:

#include 
#include 

char buf[30];

int
main(void)
{
	bool george;

	george = 7;
	sprintf(buf, "george is %d\n", george);

	return 0;
}

compiled for an ATmega128 works OK. Here's the debugger session:

(gdb) targ rem :1212
Remote debugging using :1212
0x00000000 in __vectors ()
(gdb) load
Loading section .data, size 0xe lma 0x7a6
Loading section .text, size 0x7a6 lma 0x0
Start address 0x0, load size 1972
Transfer rate: 15776 bits in <1 sec, 31 bytes/write.
(gdb) b main
Breakpoint 1 at 0xd2: file foo.c, line 12.
(gdb) c
Continuing.

Breakpoint 1, main () at foo.c:12
(gdb) n
(gdb) p buf
$3 = "george is 1\n", '\0' 

Note that the above works for both, C++ as well as C99 (which I've
been using here in the debugger session, but I've verified the
assembler output from the C++ compiler as well).

As long as you use bool the way it was intented (e.g. you don't cast
other integer expressions to it), it works well.

Compiler used as avr-gcc 3.4.1. (I'd be surprised if they broke it in
3.4.2, but you might prove me wrong with a similar debugger session if
you want. All known recent breakage has been introduced between 3.3.x
and 3.4.)

I've also replaced the assignment of a constant integer by calling a
function returning `int', the generated code still looks OK, i.e. it
properly tests the function's result for being non-zero, and assigns 0
or 1 to `george'.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

steve17 wrote:
So it seems that this is a bug in the AVR port of GCC Where would I report this bug? Would it be the gcc.gnu.org or is there some other place that ports GCC to AVR?

Yes bugs for the AVR port of GCC go to the main GCC bug database at gcc.gnu.org. Specifically go to the bottom of that page and on the left are links on where to report a bug.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dl8dtl wrote:
I can't seem to reproduce your bug. }.

I'm not sure if you are talking about my problem or not.

My problem is with C++ where bool and true are built in to the compiler, or so I think.

I've never tried using sprintf etc. and I've never included stdio.h or stdbool.h, though stdbool.h might get included somehow. If you have a debugger though, it ought to be easy to test with or without sprintf.

My bug is simple:

bool george = true.

If(george == true)   {
   // never gets here.
   // put whatever you want here so you can set a breakpoint.
   int sam = george;
   }

// you can then do something like this, if you want.
int georgeValue = george;
int trueValue = true;

I think you will find that george has a value of 0x01 and true has a value of 0xffff. As "true" is a keyword (or so I think) I don't know what that means.

The problem is that (george == true) is evaluated as false.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bool, true and false are standard types in C99 as well (that's why my
little program works for both).

You're right, for C++, including is not required
(according to the comments in that header file, supporting it for C++
is a GCC extension -- for C99, this file is required though), but
nevertheless, that little program works for me as well there. I
extended it to:

sprintf(buf, "george is %d, true is %d\n", george, true);

and the resulting assembler code makes it pretty clear that both,
george and true push both a literal number 1 onto the stack:

        ldi r24,lo8(1)
        ldi r25,hi8(1)
        push r25
        push r24
        push r25
        push r24
        ldi r24,lo8(.LC0)
        ldi r25,hi8(.LC0)
        push r25
        push r24
        ldi r24,lo8(buf)
        ldi r25,hi8(buf)
        push r25
        push r24
        rcall sprintf

You can clearly see that #1 is loaded into rr24/25 once, but they are
pushed twice into the arg list of sprintf.

I also played around with some form of `if' statements, but still
cannot reproduce your results in any way.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for testing this. I finally found my problem. I did have true and false defined in one of my own header files. I guess I stuck it in there sometime in the past to compile some C code.

So there isn't anything wrong with the compiler. Just something wrong with my head. :)

I finally got the debugger working for C++ also. I got Studio version 4.10 and use -g dwarf-2. It works fine but it makes my program a lot bigger. It doubles the size of the text section. Probably something else I'm doing wrong.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> (C++) ... It doubles the size of the text section. Probably
> something else I'm doing wrong.

GCC 3.4.x apparently has some optimization bugs when being used for
C++ (at least for the AVR). If you can, compare the code against GCC
3.3.x (which usually compiled similar results for identical code in
both frontends).

Also, make sure the exception handling is turned off. This is
supposed to be the default for the AVR target, but who knows?

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So after 30 years, we still dont agree on whether bool variables should be evaluated in the LSB or in ANY bit of the byte/word. I just use an int, and its either zero or non zero. That's boolean enough for me. What about you?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The `bool' type isn't 30 years old, it's a C++ or C99 feature (for
C++, it's always there, for C99, it can be requested via ).
And, you don't have to "agree" on anything there, it's all automatic.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:
So after 30 years, we still dont agree on whether bool variables should be evaluated in the LSB or in ANY bit of the byte/word. I just use an int, and its either zero or non zero. That's boolean enough for me. What about you?

And using an int for a boolean value on the AVR is such a waste of space: for most AVR compilers an int is 16 bits.