Does 0<(unsigned Short)0x8000 Hold? | C Programming
Có thể bạn quan tâm
- Forums New posts Search forums
- Members Current visitors
Search
Everywhere Threads This forum This thread Search titles only Search Advanced search…- New posts
- Search forums
- Forums
- Archive
- Archive
- C Programming
- Thread starter Francois Grieu
- Start date Mar 27, 2012
Francois Grieu
I just tested my code for portability problems on systems where int is 16-bit, and found one such system where #include <stdio.h> int main(void) { printf("%d\n", 0<(unsigned short)0x8000 ); return 0; } outputs 0. If I change 0< to 0u<, the output is 1. Is that a bug in this compiler, w.r.t. C99? As an aside, 6.5.8p2 puzzles me; it reads: "One of the following shall hold: — both operands have real type; — both operands are pointers to qualified or unqualified versions of compatible object types; or — both operands are pointers to qualified or unqualified versions of compatible incomplete types. (..)" Would my example imply conversion to *real*, at least conceptually ?! As an aside of the aside, I do not understand the third option in the constraint, and it has been removed in N1570. TIA, Francois Grieu HHarald van Dijk
I just tested my code for portability problems on systems where int is 16-bit, and found one such system where #include <stdio.h> int main(void) { printf("%d\n", 0<(unsigned short)0x8000 ); return 0; } outputs 0. If I change 0< to 0u<, the output is 1. Is that a bug in this compiler, w.r.t. C99? Click to expand...unsigned short promotes to int if all values can be represented in int, otherwise it promotes to unsigned int (6.3.1.1p2), so yes, that looks like a bug.
As an aside, 6.5.8p2 puzzles me; it reads: "One of the following shall hold: — both operands have real type; — both operands are pointers to qualified or unqualified versions of compatible object types; or — both operands are pointers to qualified or unqualified versions of compatible incomplete types. (..)" Would my example imply conversion to *real*, at least conceptually ?! Click to expand...Integer types and floating point types are together called real types (6.2.5p17); yes, there is an implicit conversion to a real type, and that type is unsigned int.
As an aside of the aside, I do not understand the third option in the constraint, and it has been removed in N1570. Click to expand...It seems to allow comparisons between two void * values, or between two int(*)[] values. It seems silly to allow that but not also allow a comparison between f.e. a void * and a char *, but I'm not sure why it was removed entirely. J
James Kuyper
I just tested my code for portability problems on systems where int is 16-bit, and found one such system where #include <stdio.h> int main(void) { printf("%d\n", 0<(unsigned short)0x8000 ); return 0; } outputs 0. If I change 0< to 0u<, the output is 1. Is that a bug in this compiler, w.r.t. C99? Click to expand...INT_MAX is allowed to be as low as 0x7FFF, and that's presumably true on a 16-bit system (though there's always been a lot of debate about what "N-bit system" really means). If so, conversion of (unsigned short)0x8000 to int would produce a negative value unless int has a sign-and-magnitude type. But if INT_MAX is 0x7FFF, then (unsigned char)0x8000 must be promoted to "unsigned int", rather than "int" (6.3.1.1p2), and therefore 0 must also be converted to unsigned int, before evaluating the expression. As a result that expression would be equivalent to 0U < 0x8000U, which is still guaranteed to have a value of 1. I'd say this is a bug in the compiler.
As an aside, 6.5.8p2 puzzles me; it reads: "One of the following shall hold: — both operands have real type; — both operands are pointers to qualified or unqualified versions of compatible object types; or — both operands are pointers to qualified or unqualified versions of compatible incomplete types. (..)" Would my example imply conversion to *real*, at least conceptually ?! Click to expand..."The integer and real floating types are collectively called real types." (6.2.5p17), therefore no conversion to a real type is required. As a result, the usual arithmetic conversions require that the integer promotions be applied to both operands (6.3.1.8p1).
As an aside of the aside, I do not understand the third option in the constraint, ... Click to expand...You're referring to "both operands [of a relational operator] are pointers to qualified or unqualified versions of compatible incomplete types."? I think the trickiest concept used in that sentence is "pointers to ... compatible incomplete types". Is that what you're having trouble with? Each of the following declarations defines a pointer to an incomplete type: int (*p_incomplete_array)[]; struct flexible_array { size_t count; int member[]; } *pfa; // No definition provided for struct my_struct struct my_struct *pms; void *pv;
... and it has been removed in N1570. Click to expand...I can confirm that it has been removed. The implication would seem to be that it's no longer possible to compare pointers to incomplete types for relative order. I find this surprising. Am I misunderstanding it? If not was it deliberately removed, or an accident? If deliberate, what was the rationale for doing so? B
Ben Bacarisse
Francois Grieu said: I just tested my code for portability problems on systems where int is 16-bit, and found one such system where #include <stdio.h> int main(void) { printf("%d\n", 0<(unsigned short)0x8000 ); return 0; } outputs 0. If I change 0< to 0u<, the output is 1. Is that a bug in this compiler, w.r.t. C99? Click to expand...It looks wrong to me. GCC says 1 on my machine and that's what I'd expect.
As an aside, 6.5.8p2 puzzles me; it reads: "One of the following shall hold: — both operands have real type; — both operands are pointers to qualified or unqualified versions of compatible object types; or — both operands are pointers to qualified or unqualified versions of compatible incomplete types. (..)" Would my example imply conversion to *real*, at least conceptually ?! Click to expand...Depends on what "conceptually" means here! 6.2.5 p 17 says: The type char, the signed and unsigned integer types, and the enumerated types are collectively called integer types. The integer and real floating types are collectively called real types. so it's really just a catch-all term like arithmetic type.
As an aside of the aside, I do not understand the third option in the constraint, and it has been removed in N1570. Click to expand...It makes sense to remove it. You can compare two pointers to incomplete types for equality, but <, >, etc are defined in terms of sub-objects in a array, so only pointers to object type make good sense. Some previously well-defined code (albeit not very useful code) will now require a diagnostic. F
Francois Grieu
(..) that expression would be equivalent to 0U < 0x8000U (..) Click to expand...I get to that also. It is a bug in the compiler. Main question solved.
"The integer and real floating types are collectively called real types." (6.2.5p17), Click to expand...Ah! First aside solved. I read "real" and understood "floating".
(..) I think the trickiest concept used in that sentence is "pointers to ... compatible incomplete types". Is that what you're having trouble with? Yes. Each of the following declarations defines a pointer to an incomplete type: int (*p_incomplete_array)[]; struct flexible_array { size_t count; int member[]; } *pfa; // No definition provided for struct my_struct struct my_struct *pms; void *pv; Click to expand...Ah, thanks for the illustration! Now I see 6.2.5p1, defining "incomplete type" as one of "types that describe objects but lack information needed to determine their sizes". So when I'm using a pointer to void, I'm using an "incomplete type", like Mr. Jourdain is using prose [I choose to never use the other forms, for portability].
I can confirm that it has been removed. The implication would seem to be that it's no longer possible to compare pointers to incomplete types for relative order. I find this surprising. Am I misunderstanding it? If not was it deliberately removed, or an accident? If deliberate, what was the rationale for doing so? Click to expand...Indeed, comparing pointers to void referring to elements in the same struct or array seems like a feature that could help on occasions, was OK in C99, and seems gone from C2011 for no apparent reason. I second the question. Francois Grieu T
Tim Rentsch
Francois Grieu said: I just tested my code for portability problems on systems where int is 16-bit, and found one such system where #include <stdio.h> int main(void) { printf("%d\n", 0<(unsigned short)0x8000 ); return 0; } outputs 0. If I change 0< to 0u<, the output is 1. Is that a bug in this compiler, w.r.t. C99? Click to expand...Yes. There is a simple argument that it is: 1. The value 0x8000 is always representable as an unsigned short. 2. The rules for 'integer promotions' always preserve value. 3. The rules for 'usual arithmetic conversions' preserve value for all operand values that are non-negative. (A negative operand value might become non-negative due to UAC, but all non-negative values don't change under UAC.) Since 0 < 0x8000 must hold, 0 < (unsigned short) 0x8000 must hold, because ultimately the same mathematical comparison is done.
As an aside, 6.5.8p2 puzzles me; [snip] As an aside of the aside, I do not understand the third option in the constraint, and it has been removed in N1570. Click to expand...The removal is not a change but just indicative of a change in nomenclature. In C99, there are incomplete types and object types. In N1570, there are incomplete object types and complete object types, which together make up object types. So in N1570, both complete and incomplete types are included under the now more general 'object type' term, and hence the third option in C99 is folded into the second option in N1570. B
Ben Bacarisse
Ben Bacarisse said: Francois Grieu <[email protected]> writes: It makes sense to remove it. Click to expand...No it didn't! This part of my reply was nonsense. It's perfectly possible to well-define relative comparisons between pointers to incomplete types. It's good to see that the change is just due to a change in terminology. J
James Kuyper
No it didn't! This part of my reply was nonsense. It's perfectly possible to well-define relative comparisons between pointers to incomplete types. It's good to see that the change is just due to a change in terminology. Click to expand...Could you explain the change in terminology? I thought about the possibility that something like that was involved, but I didn't notice anything relevant. H
Harald van Dijk
Could you explain the change in terminology? I thought about the possibility that something like that was involved, but I didn't notice anything relevant. Click to expand...I didn't notice it either, but as Tim Rentsch pointed out, the change is in 6.2.5p1. Old: "Types are partitioned into object types (types that fully describe objects), function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes)." New: "Types are partitioned into object types (types that describe objects) and function types (types that describe functions)." J
James Kuyper
I didn't notice it either, but as Tim Rentsch pointed out, the change is in 6.2.5p1. Click to expand...Ah - that explains why I didn't know what Ben was talking about. I've got Tim killfiled - not because he's a spammer or any other kind of idiot, but just because I found that I frequently ended up wasting lots of time in long discussions with him disagreeing about excessively subtle issues without either of us ever managing to change the mind of the other. That would not have mattered if the discussions had been fun, or at least interesting, but I just found them frustrating - which could just as easily have been my fault as his. P
Philipp Klaus Krause
I just tested my code for portability problems on systems where int is 16-bit, and found one such system where […] Click to expand...Which system? Philipp F
Francois Grieu
Yes. There is a simple argument that it is: 1. The value 0x8000 is always representable as an unsigned short. 2. The rules for 'integer promotions' always preserve value. 3. The rules for 'usual arithmetic conversions' preserve value for all operand values that are non-negative. (A negative operand value might become non-negative due to UAC, but all non-negative values don't change under UAC.) Since 0 < 0x8000 must hold, 0 < (unsigned short) 0x8000 must hold, because ultimately the same mathematical comparison is done. Click to expand...Nice, reusable argument. Thanks.
Again, thanks for the synthetic explanation. Francois Grieu FAs an aside, 6.5.8p2 puzzles me; [snip] As an aside of the aside, I do not understand the third option in the constraint, and it has been removed in N1570. Click to expand...The removal is not a change but just indicative of a change in nomenclature. In C99, there are incomplete types and object types. In N1570, there are incomplete object types and complete object types, which together make up object types. So in N1570, both complete and incomplete types are included under the now more general 'object type' term, and hence the third option in C99 is folded into the second option in N1570. Click to expand...
Francois Grieu
The CPU was a regular PC, running cmd.exe of Windows XP SP3; the failing compiler was Turbo C++ 1.01 (released 1991) in C mode. I am NOT using that compiler for anything but test. I there is a more modern 80x86 16-bit compiler (defined as UINT_MAX==0xFFFF, perhaps as an option), I want to know. My usual 16-bit targets include - ST7/ST19/ST21/ST23 - PIC18 - 8051 and derivatives and (at least with the compilers I now use for production) pass this test. My customer's platform include - 68K derivatives (including ColdFire) - ARM derivatives - MIPS derivatives - 80x86 derivatives For some of my customer's target systems, the option exist to compile with a 16-bit int (e.g. gcc -mshort ), and I have no idea of my customer's choice. Francois Grieu KI just tested my code for portability problems on systems where int is 16-bit, and found one such system where […] Click to expand...Which system? Click to expand...
Kaz Kylheku
Hahaha, you wasted everyone's time answering questions about irrelevant old cruft. Good job! Post replyThe CPU was a regular PC, running cmd.exe of Windows XP SP3; the failing compiler was Turbo C++ 1.01 (released 1991) in C mode. Click to expand...I just tested my code for portability problems on systems where int is 16-bit, and found one such system where […] Click to expand...Which system? Click to expand...
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.
Ask a QuestionSimilar Threads
Is the expression 1 ? "123" : "1234" a valid one ? | 6 | Apr 24, 2012 |
A more verbose discussion of const and conversions... (part 2) | 0 | Nov 30, 2006 |
Types | 58 | Dec 10, 2006 |
comp.lang.c Answers (Abridged) to Frequently Asked Questions (FAQ) | 0 | Mar 1, 2008 |
comp.lang.c Answers (Abridged) to Frequently Asked Questions (FAQ) | 0 | Jan 12, 2008 |
comp.lang.c Answers (Abridged) to Frequently Asked Questions (FAQ) | 0 | Dec 15, 2007 |
comp.lang.c Answers (Abridged) to Frequently Asked Questions (FAQ) | 0 | Mar 15, 2008 |
comp.lang.c Answers (Abridged) to Frequently Asked Questions (FAQ) | 0 | Apr 1, 2008 |
Members online
No members online now. Total: 207 (members: 0, guests: 207) Robots: 76Forum statistics
Threads 474,017 Messages 2,570,298 Members 46,922 Latest member PhilipBarnLatest Threads
- Javascript set language function issue
- Started by crypt_net010
- Yesterday at 4:54 PM
- Return pointer from void only gives the memory address
- Started by Steffen595
- Yesterday at 2:49 AM
- Flutter web
- Started by Jean-Marie
- Saturday at 11:56 PM
- Strange result using "for(in... " iteration
- Started by jimandy
- Saturday at 7:38 PM
- Multithreaded Server Under Load: Real-Time Packet Exchange with 5 Clients
- Started by Infinityhost
- Friday at 7:32 PM
- Python and HTML
- Started by HTMLpigeon64
- Friday at 7:29 PM
- Urgent Help Needed: Supporting Education and Family Through Hard Work
- Started by miantsafanirina
- Friday at 8:26 AM
- Accountability intro
- Started by bauble
- Thursday at 9:44 AM
- I want to convert Outlook data files to MBOX manually
- Started by Techykaus24
- Thursday at 8:33 AM
- Gray Scott model in FEniCS
- Started by Lonny Petersen
- Wednesday at 7:13 AM
- Forums
- Archive
- Archive
- C Programming
Từ khóa » C 0x8000
-
Subtracting 0x8000 From An Int - Stack Overflow
-
You May Receive Error Code 0x80004005 Or Other Error Codes When ...
-
Problem Accessing Memory Above 0x8000
-
Bitwise And - C Board
-
Whether 0x8000 Is Voilating MISRA C-2012 Rule 7.2 ?
-
Understand Configuration Register Usage On All Routers - Cisco
-
Thread: What Does #define IP_RF 0x8000 Mean? - CodeGuru Forums
-
How To Fix Error Code 0x80004005 - Lifewire
-
SOLVED: How To Fix Error 0x80004005
-
Error 0x80070002 Occurs While Launching Or Installing A PC Game
-
[PDF] Code From 3c59x.c