Invalid Compiler Warning?
Author |
Message |
Thomas Matthe #1 / 25
|
Invalid Compiler Warning?
Hi, I have the following test program: #include <stdio.h> typedef unsigned char UINT8; int main(void) { UINT8 value = ~0; printf("Value: 0x%02X\n", value); return 0; Quote: }
The ARM Compiler (Arm Project Manager) gives me the warning: Warning: "uint8.c"; line 7 implicit cast (to 'unsigned char') overflow The GNU Gcc compiler, 2.95.3, does not issue any warnings. I used the command line: gcc -Wall -o uint8 uint8.c The _Harbison_and_Steele_ book does not mention anything about warnings for bitwise negation (section 7.5.5). Which compiler is correct? -- Thomas Matthews
|
Sun, 03 Apr 2005 23:21:06 GMT |
|
|
Jirka Klau #2 / 25
|
Invalid Compiler Warning?
Quote:
> Hi, > I have the following test program: > #include <stdio.h> > typedef unsigned char UINT8; > int main(void) > { > UINT8 value = ~0;
If int is e.g. 16bit wide, ~0 would produce 0xFFFF (2's complement). And this overflows 8bit unsigned char. Jirka
|
Sun, 03 Apr 2005 23:29:02 GMT |
|
|
Scott Fluhre #3 / 25
|
Invalid Compiler Warning?
Quote: > Hi, > I have the following test program: > #include <stdio.h> > typedef unsigned char UINT8; > int main(void) > { > UINT8 value = ~0; > printf("Value: 0x%02X\n", value); > return 0; > } > The ARM Compiler (Arm Project Manager) gives me the warning: > Warning: "uint8.c"; line 7 implicit cast (to 'unsigned char') overflow > The GNU Gcc compiler, 2.95.3, does not issue any warnings. > I used the command line: gcc -Wall -o uint8 uint8.c > The _Harbison_and_Steele_ book does not mention anything about warnings > for bitwise negation (section 7.5.5). > Which compiler is correct?
They both are. According to the Standard, there is no mandatory error message there. However, any compiler is free to produce any diagnostics (e.g. warning messagess) it feels like. BTW: the warning isn't about the bitwise negation; it's for initializing a object of type UINT8 with a value that does not fit into that type. The expression ~0 is (at a minimum) 65535, and values of that size do not fit within the ARM compiler's unsigned char type. This is not an error; for unsigned types, there is a defined method of doing the conversion. However, the ARM compiler tried to be helpful in telling you that it was doing so. To quiet the compiler, you could try: UINT8 value = (UINT8)~0; -- poncho
|
Sun, 03 Apr 2005 23:40:13 GMT |
|
|
Eric Sosma #4 / 25
|
Invalid Compiler Warning?
Quote:
> [...] > typedef unsigned char UINT8; > int main(void) > { > UINT8 value = ~0; > [...] > The ARM Compiler (Arm Project Manager) gives me the warning: > Warning: "uint8.c"; line 7 implicit cast (to 'unsigned char') overflow > The GNU Gcc compiler, 2.95.3, does not issue any warnings. > I used the command line: gcc -Wall -o uint8 uint8.c > The _Harbison_and_Steele_ book does not mention anything about warnings > for bitwise negation (section 7.5.5). > Which compiler is correct?
Both. The compiler is permitted to issue whatever warnings its implementors thought might be helpful. It can complain or be silent about unreachable statements, about suspicious type conversions, or about spelling errors in your commemts. Some compilers, for example, will issue a warning message for if (x = 0) printf ("Warning: x is zero!\n"); even though it's perfectly valid C code -- and most programmers consider this a Good Thing because it draws their attention to the fact that this perfectly valid code probably doesn't do what was intended. Count your blessings. --
|
Mon, 04 Apr 2005 02:57:06 GMT |
|
|
Kevin Brace #5 / 25
|
Invalid Compiler Warning?
Quote: > The ARM Compiler (Arm Project Manager) gives me the warning: > Warning: "uint8.c"; line 7 implicit cast (to 'unsigned char') overflow > The GNU Gcc compiler, 2.95.3, does not issue any warnings. > I used the command line: gcc -Wall -o uint8 uint8.c
Other people have answered your particular question, but I'll take the opportunity to point out that the Norcroft (ARM) compiler is a lot stricter than gcc, and generally more standard-conformant, so you will often be getting warnings or errors you may not expect if you're used to gcc. It's generally right though (or for warnings like this, just trying to be helpful). Tragically, ARM have gradually been reducing the strictness of the compiler in response to customer demand :( -- Kevin Bracey http://www.bracey-griffith.freeserve.co.uk/
|
Mon, 04 Apr 2005 03:33:57 GMT |
|
|
Thomas Matthew #6 / 25
|
Invalid Compiler Warning?
Quote:
> > Hi, > > I have the following test program: > > #include <stdio.h> > > typedef unsigned char UINT8; > > int main(void) > > { > > UINT8 value = ~0; > If int is e.g. 16bit wide, ~0 would produce 0xFFFF (2's complement). > And this overflows 8bit unsigned char. > Jirka
But 8-bit wide, ~0 should produce 0xFF (one's complement). Why does it overflow? I don't see why a 1's complement should oveflow. -- Thomas Matthews
|
Mon, 04 Apr 2005 05:46:44 GMT |
|
|
Thomas Matthew #7 / 25
|
Invalid Compiler Warning?
Quote:
> > Hi, > > I have the following test program: > > #include <stdio.h> > > typedef unsigned char UINT8; > > int main(void) > > { > > UINT8 value = ~0; > > printf("Value: 0x%02X\n", value); > > return 0; > > } > > The ARM Compiler (Arm Project Manager) gives me the warning: > > Warning: "uint8.c"; line 7 implicit cast (to 'unsigned char') > overflow > > The GNU Gcc compiler, 2.95.3, does not issue any warnings. > > I used the command line: gcc -Wall -o uint8 uint8.c > > The _Harbison_and_Steele_ book does not mention anything about warnings > > for bitwise negation (section 7.5.5). > > Which compiler is correct? > They both are. According to the Standard, there is no mandatory error > message there. However, any compiler is free to produce any diagnostics > (e.g. warning messagess) it feels like. > BTW: the warning isn't about the bitwise negation; it's for initializing a > object of type UINT8 with a value that does not fit into that type. The > expression ~0 is (at a minimum) 65535, and values of that size do not fit > within the ARM compiler's unsigned char type. This is not an error; for > unsigned types, there is a defined method of doing the conversion. However, > the ARM compiler tried to be helpful in telling you that it was doing so. > To quiet the compiler, you could try: > UINT8 value = (UINT8)~0; > -- > poncho
Why is ~0 a 16 bit quantity? The compiler also yelled at: UINT8 = ~'\0'; -- Thomas
|
Mon, 04 Apr 2005 05:48:08 GMT |
|
|
Thomas Matthew #8 / 25
|
Invalid Compiler Warning?
Quote:
> > The ARM Compiler (Arm Project Manager) gives me the warning: > > Warning: "uint8.c"; line 7 implicit cast (to 'unsigned char') overflow > > The GNU Gcc compiler, 2.95.3, does not issue any warnings. > > I used the command line: gcc -Wall -o uint8 uint8.c > Other people have answered your particular question, but I'll take the > opportunity to point out that the Norcroft (ARM) compiler is a lot stricter > than gcc, and generally more standard-conformant, so you will often be > getting warnings or errors you may not expect if you're used to gcc. It's > generally right though (or for warnings like this, just trying to be > helpful). > Tragically, ARM have gradually been reducing the strictness of the compiler > in response to customer demand :( > -- > Kevin Bracey > http://www.bracey-griffith.freeserve.co.uk/
I'm just confused how an 8-bit quantity could overflow an an 8-bit variable. If I assign the constant 36 to an unsigned char variable, there is no complaint. One is led to believe that 36 is an 8-bit quantity. So why is ~0 considered to be a 16-bit quantity? Why not 32 or 64? My understanding was that the expression '~0' would be calculated in terms of unsigned character since that was the type on the left-hand side. -- Thomas Matthews
|
Mon, 04 Apr 2005 05:51:53 GMT |
|
|
Ben Pfaf #9 / 25
|
Invalid Compiler Warning?
Quote:
> If I assign the constant 36 to an unsigned char variable, there > is no complaint. One is led to believe that 36 is an 8-bit > quantity.
It isn't. It is at least 16 bits in size, because small integer constants in C have type int and int is at least 16 bits in size. Quote: > So why is ~0 considered to be a 16-bit quantity? > Why not 32 or 64?
It could be 32 or 64 if that's the size of your int. Quote: > My understanding was that the expression '~0' would be calculated in terms > of unsigned character since that was the type on the left-hand side.
Your understanding is incorrect. The type on the left-hand side of an assignment does not affect how arithmetic is performed on the right-hand side. -- "Am I missing something?" --Dan Pop
|
Mon, 04 Apr 2005 05:54:03 GMT |
|
|
Ben Pfaf #10 / 25
|
Invalid Compiler Warning?
Quote:
> Why is ~0 a 16 bit quantity?
Because 0 has type int and you're (presumably) using a system with a 16-bit int. Small integer constants in C have type int. Quote: > The compiler also yelled at: > UINT8 = ~'\0';
0 and '\0' have the same type and value. Both have type int and value zero. And you can't assign to a type, only to a variable. -- "The expression isn't unclear *at all* and only an expert could actually have doubts about it" --Dan Pop
|
Mon, 04 Apr 2005 05:52:26 GMT |
|
|
Kevin Brace #11 / 25
|
Invalid Compiler Warning?
Quote: > I'm just confused how an 8-bit quantity could overflow an an 8-bit > variable.
That's not unreasonable in this case. Quote: > If I assign the constant 36 to an unsigned char variable, there is no > complaint. One is led to believe that 36 is an 8-bit quantity.
That's because 36 fits into an unsigned char. It's not really a question of being "8-bit" or "16-bit". It's just a question of whether the value fits. Quote: > So why is ~0 considered to be a 16-bit quantity?
32-bit, actually, in the case of the ARM compiler. Here's how it goes: 1) 0 is an "int". 2) An "int" is 32 bits on this compiler. 3) Thus ~0 = 0xFFFFFFFF. 4) 0xFFFFFFFF does not fit into an unsigned char. 5) Thus the compiler gives you a 'helpful' warning (although the behaviour is well defined, and you must end up with 0xFF in 'a'). [Pedants: char being 8-bit here]. What you'd like is a way of doing an 8-bit "~" operation. C won't let you do this, unfortunately, as all operands are promoted to at least "int" before operations take place. One way to shut the compiler up would be to define a simple macro: #define INVERTCHAR(a) ((a) ^ (unsigned char) -1) unsigned char a = INVERTCHAR(0); The other way is just to explicitly cast, which makes the compiler think you know what you're doing: unsigned char a = (unsigned char) ~0; Alternatively, there may be a compiler option to disable that particular warning. Quote: > My understanding was that the expression '~0' would be calculated in terms > of unsigned character since that was the type on the left-hand side.
Afraid not, expressions always evaluate the same way, regardless of where they're going to end up. Same problem as the frequently-asked "float f = 1 / 2;" not working. -- Kevin Bracey http://www.bracey-griffith.freeserve.co.uk/
|
Mon, 04 Apr 2005 06:50:22 GMT |
|
|
CBFalcone #12 / 25
|
Invalid Compiler Warning?
Quote:
> > The ARM Compiler (Arm Project Manager) gives me the warning: > > Warning: "uint8.c"; line 7 implicit cast (to 'unsigned char') overflow > > The GNU Gcc compiler, 2.95.3, does not issue any warnings. > > I used the command line: gcc -Wall -o uint8 uint8.c > Other people have answered your particular question, but I'll take the > opportunity to point out that the Norcroft (ARM) compiler is a lot stricter > than gcc, and generally more standard-conformant, so you will often be > getting warnings or errors you may not expect if you're used to gcc. It's > generally right though (or for warnings like this, just trying to be > helpful).
gcc -W -Wall -ansi -pedantic -O2 will find more problem areas. (without the -On it won't find unused variables). You can also use splint. --
Available for consulting/temporary embedded and systems. <http://cbfalconer.home.att.net> USE worldnet address!
|
Mon, 04 Apr 2005 08:28:46 GMT |
|
|
Jack Klei #13 / 25
|
Invalid Compiler Warning?
On Wed, 16 Oct 2002 23:50:22 +0100, Kevin Bracey
Quote:
> > I'm just confused how an 8-bit quantity could overflow an an 8-bit > > variable. > That's not unreasonable in this case. > > If I assign the constant 36 to an unsigned char variable, there is no > > complaint. One is led to believe that 36 is an 8-bit quantity. > That's because 36 fits into an unsigned char. It's not really a question of > being "8-bit" or "16-bit". It's just a question of whether the value fits. > > So why is ~0 considered to be a 16-bit quantity? > 32-bit, actually, in the case of the ARM compiler. Here's how it goes: > 1) 0 is an "int". > 2) An "int" is 32 bits on this compiler. > 3) Thus ~0 = 0xFFFFFFFF. > 4) 0xFFFFFFFF does not fit into an unsigned char. > 5) Thus the compiler gives you a 'helpful' warning (although the behaviour > is well defined, and you must end up with 0xFF in 'a'). [Pedants: > char being 8-bit here]. > What you'd like is a way of doing an 8-bit "~" operation. C won't let you do > this, unfortunately, as all operands are promoted to at least "int" before > operations take place.
In fact the ARM core can't do pure 8 bit operations at all. It is a much "purer" C machine than something like the x86 with its multiple register sizes. When an ARM processor accesses a (signed or unsigned) char (8 bits on ARM) or short (16 bits on ARM), the value is always automatically sign or zero extended to fill a 32 bit register. All integer arithmetic and logical operations are always performed on the full 32 bit register. There are no 8 or 16 bit instructions. Quote: > One way to shut the compiler up would be to define a simple macro: > #define INVERTCHAR(a) ((a) ^ (unsigned char) -1) > unsigned char a = INVERTCHAR(0); > The other way is just to explicitly cast, which makes the compiler think you > know what you're doing: > unsigned char a = (unsigned char) ~0; > Alternatively, there may be a compiler option to disable that particular > warning. > > My understanding was that the expression '~0' would be calculated in terms > > of unsigned character since that was the type on the left-hand side. > Afraid not, expressions always evaluate the same way, regardless of where > they're going to end up. Same problem as the frequently-asked > "float f = 1 / 2;" not working.
Beyond that, there is no expression involving an arithmetic or logical operation in C that is ever carried out on integer types smaller than signed or unsigned int. char and short types are always promoted to signed or unsigned int (or to a larger type) in these types of expressions. -- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
|
Mon, 04 Apr 2005 14:06:56 GMT |
|
|
Kevin Brace #14 / 25
|
Invalid Compiler Warning?
Quote: > In fact the ARM core can't do pure 8 bit operations at all. It is a > much "purer" C machine than something like the x86 with its multiple > register sizes. > When an ARM processor accesses a (signed or unsigned) char (8 bits on > ARM) or short (16 bits on ARM), the value is always automatically sign > or zero extended to fill a 32 bit register. All integer arithmetic > and logical operations are always performed on the full 32 bit > register. There are no 8 or 16 bit instructions.
They're beginning to appear. The new-fangled 16-bit memory access instructions were the start of the downhill slide, but newer revisions of the architecture are growing 16x16->32 multiplies, parallel 16+16->16 additions, etc etc. Blurgh. Nothing that a compiler can easily take advantage of terribly easily. It's not exactly the Acorn/Advanced "RISC" Machine anymore - architecture 6 adds four times as many instructions as the first ARM had in total :) But yes, it's an interesting point that the automatic promotion to int was almost designed for the ARM; it would be very painful having to keep truncating results to 8 or 16 bits in the middle of expressions. I've been working on the ARM so long, I'd forgotten that other weird processors used to have variable width registers. -- Kevin Bracey http://www.bracey-griffith.freeserve.co.uk/
|
Mon, 04 Apr 2005 16:44:54 GMT |
|
|
Dan P #15 / 25
|
Invalid Compiler Warning?
Quote:
>> The ARM Compiler (Arm Project Manager) gives me the warning: >> Warning: "uint8.c"; line 7 implicit cast (to 'unsigned char') overflow >> The GNU Gcc compiler, 2.95.3, does not issue any warnings. >> I used the command line: gcc -Wall -o uint8 uint8.c >Other people have answered your particular question, but I'll take the >opportunity to point out that the Norcroft (ARM) compiler is a lot stricter >than gcc,
This is a pointless remark: compilers either are conforming or not. Quote: >and generally more standard-conformant,
Another pointless remark, for the same reason. Quote: >so you will often be >getting warnings or errors you may not expect if you're used to gcc.
When used in conforming mode, gcc produces all the diagnostics required by the standard, AFAICT. So, if you get an error diagnostic from another compiler, while gcc -ansi -pedantic silently accepts the code, it is more likely that the other compiler is broken (by error diagnostic I mean a diagnostic that prevents the successful translation and execution of the program). Of course, "warnings" are a completely different issue, each implementor has his own ideas about what is a helpful warning. Quote: >It's >generally right though (or for warnings like this, just trying to be >helpful).
But that's the real problem: by warning about this perfectly correct program construct, the compiler effectively forces the programmer to introduce an *unneeded* cast (or to live with the annoying diagnostic). Many people consider unneeded casts to be harmful. Therefore, such warnings are more annoying than helpful. Dan -- Dan Pop DESY Zeuthen, RZ group
|
Mon, 04 Apr 2005 19:27:24 GMT |
|
|
Page 1 of 2
|
[ 25 post ] |
|
Go to page:
[1]
[2] |
|