I can't remember all the details and rationale for it, it's been a long time.bob wrote:That is a new one on me. I can't think of a single platform I have not worked on in the past 40 years, and none of them had issues with a -0, because that doesn't exist in 2's complement. In the days of packed decimal, yes. But for an 8-bit char (and of course not all machines even had 8 bit chars, univac/cdc used 6 bits as an example).Carey wrote:In the old days of 32 bit systems, that was fairly true. But it was more convention than requirement because C didn't mandate anything back then.bob wrote:I actually have looked at this. Many times. And yes, I am aware that the standard does not say what "long" means, exactly, just that it means >= int in all cases.Carey wrote:Bob,bob wrote:DId you _read_ my last comment? Windows vista 64 bits + 64 bit gcc gives the expected sizeof(long) = 8. So I _did_ test windows. I don't use the microsoft C++ compiler so I have no idea what they do. But anyone that uses sizeof(long)=anything_other_than_8 on a 64 bit architecture is certainly brain-dead. But MS has never let that stop them in the past...
BTW the crafty code you quoted has been there since 1995 or so. More recent versions use long on HAS_64BITS architectures with Linux. I've never changed the windows stuff since __int64 has been around since 1995 as well...
You might want to read the C standard documents some times. Especially the C99 one which actually talk about 64 bit integers.
However, for as long as I can remember, "long" has always been "the longest integer data type the hardware supports." Which is both logical and rational. Cray has always had int = long since it is a 64 bit architecture. With the quirk that pointers were always 32 bits because the a-registers (used for address computations) were 32 bits (eventually, early on they were 24 bits).
But when you go beyond 32 bits, the traditions break down and that's why C99 made some rules.
Again, tradition. When the C89 standard was developed, their mandate was to "codify existing practice". They had to take what was already being done and make it law. And they had to break as little existing code as possible. They didn't have much room to be creative or even fix flaws in K&R C.But for "long" on true 64 bit systems, I have yet to find a single case where long is < 64 bits, except, apparently some version of the microsoft C compiler (I have not verified which versions, if any, or if all, follow this rather odd practice). I did, long ago, verify that at least for linux, on any 64 bit platform I have tried, long = 64 bits. For X86_64, both gcc and icc follow this. And on my home windows vista 64 box, gcc does the same.
Not much more to say on the subject. Yes, the "standard" is lousy in many ways, such as why is an int always signed by default, while a char may be signed or unsigned at the whim of the compiler writer? "long long" was a non-standard extension that I used in 1995 in the first versions of Crafty when running on a 64 bit sun Sparc as well as on 32 bit X86/linux boxes.
singed vs. unsigned char again goes back to the existing implementations they had to deal with back then.
(Also, as a side point, *ONLY* unsigned char is guaranteed to copy all the unmodified bits of a byte. Signed char doesn't because it can normalize +0 and -0 on hardware that doesn't know that zero doesn't actually have a sign. And only UChar is guaranteed to actually copy all the bits where as signed char can ignore some. As I said... C89 had to deal with a lot of weird existing implementations and hardware, and trying to do that resulted in some weird wording in the standard.)
There were machines that would "sign extend" when moving a character to a word, and some that could not do so without explicit programming steps, which was what I had assumed led to the great signed/unsigned debacle.
It was something P. J. Plauger wrote about after C89 was standardized. He was heavily involved in the C89 standard throughout the whole process. (I used to love reading his columns in C Users Journal and Embedded Systems Programming. His essays in E.S.P. were the main reason I subscribed.)
He was talking about some of the odd wording in the standard and the reasoning behind it and the troubles they had trying to accomodate everybody and the old systems, etc. And then how after everything was finalized, requests for interpretations started coming and they started discovering that in some places the standard they just finished didn't actually say what they thought it did.
It was just one of those things that just stuck in my head and so to this day I make sure I'm using unsigned char's for that kind of stuff even though it'll never matter on any of the systems I'll ever use.
<laugh> There have been times over the years that I've intently wished I could move away from Microsoft stuff. But it's never worked out. Linux was just never suitable for me. I use MingW when I can, but as for the Microsoft OS WinDoze....Fortunately, I don't live in "that" world.
Maybe you didn't say 'must', but it sounded like it. It certainly sounded like 'always', though.
short is 16 bits.
int is defined as the natural word size. It is *not* required to be 32 or 64 bits. It can be 16 bits, even. It's up to whatever the compiler writer chooses. Implementation defined. On a 32 bit compiler, it should be 32 bits, of course. On a 64 bit system, 64 bit int's would be the more appropriate size.
long is defined as at least 32 bits. On a 64 bit system, it can be either 32 or 64 bits.
long long is defined as at least 64 bits.
So it is entirely possible for 'int' to be 16 bits and 'long' at 32 bits and 'long long' at 64 bits. Not likely, of course. But possible and standard conforming.
That's why the C99 standard set up the stdint.h header to provide a nice portable way the programmer can be guaranteed of having the right size integers when they need it.
For C89, it doesn't even know about 64 bit integers, and the compiler writer is on his own and the programmer should actually check to make sure. In this case, 'int' is often 32 and 'long' 64 bits. But that violates the C convention / requirement that 'int' is the machine word size.
Of course, we've had this discussion before, and I'm well aware you don't like the C99 standard because not all compilers (<cough> Microsoft <cough>) support it.
But don't go saying that 'long' *must* be 64 bits because it doesn't.
I do not believe I said "it must be 64 bits". I rather said that it has been 64 bits on _every_ 64 bit architecture and compiler combination I have tried. You can look at the Crafty Makefile to see just how comprehensive that list of architectures and O/S choices is. Apparently there is / was / could-be some MS compiler that is/was brain-dead...
But I will admit that integer sizes etc. are something that really annoys me. C says what they are and it seems like people are still going around assuming they are still what they were 20 years ago on 16 bit PC.
People are still casting pointers to 'int' or 'long' even though C99 provides a guaranteed data type to hold it. It's stupid, but people do it. Just habit. (I guess that really says it. Just like when people moved from 16 bit DOS with 'huge' pointers to 32 bits, things were a bit painful. Now that everybody is comfortable with 32 bits, they are starting to take those habits to 64 bits.)
It's just such a habit to use 'short', 'int', and 'long' that they just don't bother to use data types that are actually guaranteed to be the size they need, even if there is a chance that a too small or big size could crash the program.
(You've mentioned Cray... I remember reading a few articles from Cray's programmers complaining about the idiotic programming of 32 bit programmers. Such as cases where a 32 bit int with all bits set being equated with -1, which of course fails when Cray tried to port those programs to the 64 bit Cray systems. Or shifting bits around and expecting them to fall off the end, and then comparing them to a constant.)
And you wont get any argument from me about the arrogance of the MS Compiler writers. They still refuse to support C99 even. Not can't, but just flatly refuse. I think that if they thought they could get away with it, they'd write a whole new proprietary language and then call it C and claim it was always that way.
Back when XP came out, I bought XP Pro and told myself that I'd never buy another MS operating system.
Then when Vista came out, I actually bought a retail copy of Vista Ultimate, for the 64 bit version. Tried it, hated Vista, and stuck it on the shelf without even registering it. Then I bought three brand new computers that had Vista installed and couldn't go back to XP.
When Win 7 came out I bought the family pack and upgraded the Vista systems to Win 7.
When Win 8 comes out.....
(sigh) Somebody shoot me and put me out of my misery... (grin)
Check this out:Actually.... no. You didn't.Actually, I think that _is_ what I said.And that would even violate tradition and break a large number of programs that expect it at 32 bits. (Yes yes, I know programmer's shouldn't write a program that expects 'int' or 'long' to be a certain size without first checking, but many programs have done so in the past 25 years. Very few people these days actually bother to check to make sure a var type is the right size. They just assume 'int' is 32 bits and 'long' is probably 32 bits too.)
I'm not saying you should change your code because it's wrong or ugly or doesn't work or anything else. I'm just saying that 'long' does *NOT* have to be 64 bits. The C standard is pretty clear about that.
If you want to say that 'long' is 64 bits on the compilers you use and so that's what you program for, then that's a perfectly fine statement.
The original quote I responded to was this:bob wrote: I am using both Intel and GCC on my 64 bit linux boxes, and I can _guarantee_ you that a "long" is 64 bits:
Same code on windows produces the same results for 64 bit Windows Vista running gcc (my home box).. I don't have any 32 bit machines but did in the past, and there "long" was 32 bits as was "int"...I certainly gave an example where that is false. Because I tested a 64 bit versions of windows vista with gcc and long = 64 as expected.long is 32-bit even with a 64-bit version of Windows.
Unfortunately, this is a dead horse, since X86-64 already violates this since int is still 32 while long is 64 (excepting msvc apparently).
The problem is that by saying 'long' is 64 bits, you leave a gap at 32 bits.
C has always had the concept that 'int' is the natural word size of the program. Whether it's a 16 bit, 32 bit, 36 bit, 60 bit, 64 bit, etc. processor. As long as it's at least 16 bits.
If you make 'int' 32 bits on a 64 bit system, then you just violate 30 years of C tradition. It is allowed, but it's not.... 'expected' behavior. It's like making a compiler where 'int' is 27 bits on a 32 bit system. Sure you can do it, but you shouldn't.
Just because the horse is dead doesn't mean you should let it lay there and stink up the stables.
I know. I know. C99 just didn't come out nearly quick enough. C89 took much *much* longer to finalize than they expected, so they didn't get the chance to fix stuff until it was too late.Which would be 64 bits on x86-64 of course, but we don't have that sane approach anywhere.
'int' is supposed to be a floating size that is determined by the whatever is most appropriate for the hardware. The natural register word size that the cpu operates on most efficiently.
That's one of the reasons I don't like using int & long when there is any need for them to be more than 32 bits.
I'd much rather explcitly state the size I'm using and and use that typedef'ed type as needed. That way there is never a misunderstanding later about what size it's supposed to be.
I know that many compilers don't.I have not tested Cray compilers on x86-64 architectures, would be interesting to see what they did, since on the original cray-1 architecture (and successors thru T90) int = long = 64.
One reason for not using them is compatibility. There are a zillion compilers in existence today, and most are not C99 compatible, which would mean some ugly #ifdef stuff (Crafty already has enough just to deal with the MS C++ flaws) not to mention different systems have different libraries with different #includes needed.
That's why C99 developed stdint.h. So the programmer can depend on the sizes of integer types.
64 bit C compilers started showing up (from Cray etc.) before C99 was ratified. So many compiler writers just came up with their own solution. It would have been nice if C99 was C90 and avoided a lot of that, but of course that didn't happen.
The C99 standard provides these things to guarantee sizes to the programmer, so that no matter what compiler or what hardware is being used, they know for sure exactly what they are getting. Why not use them???
Sure, you can go by convention (ie: I tried it on the sytems I have, so it'll work everywhere!) or you use the explicitly sized types provided by C99 and guarantee it'll work and at the same time make sure that the readers understand that the var you just defined is supposed to be a certain size and not whatever the compiler writer chose.
As I've said before, this is just something that really irritates me. C gives you the tools to do it right, but most don't bother. Most don't even bother to explicitly indicate what bit size is needed for their vars. If a 'long' is good enough then they don't bother to document the bit size or do any checks to make sure it's not too small or too big.
But you can still fake it. Do a portability header as needed and typedef the appropriate things to int64_t etc. etc.
That way it's always clear to who ever is reading the code that you are explicitly expecting & requiring data sizes of a certain size.