bob wrote:Carey wrote: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...
Bob,
You might want to read the C standard documents some times. Especially the C99 one which actually talk about 64 bit integers.
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.
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).
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.
But when you go beyond 32 bits, the traditions break down and that's why C99 made some rules.
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.
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.
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.)
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...
Maybe you didn't say 'must', but it sounded like it. It certainly sounded like 'always', though.
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.
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.
Actually, I think that _is_ what I said.
Actually.... no. You didn't.
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.
'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 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.