Live data from Hacker News

Issues with porting C++ code to a 64-bit platform

viva64.com

21–30 of 45 posts

Re: Issues with porting C++ code to a 64-bit platform

#21
post #18
post #3

I had issue #2 (varags) bite me once on a C function where a NULL pointer was used as a sentinel. In C++ we normally use '0' as the name of the null pointer, as C's NULL macro ((void*)0) gives compilation errors normally (though it would have worked here). And of course, who knows what the NULL macro is defined to in C++ mode, it could be plain '0' or a compiler-specific type. With varargs '0' simply translates to in…

And this is why you use nullptr, not NULL.

Yes, this is a great reason to have nullptr, but when this occurred there wasn't even such a thing as -std=c++0x. ;)

Re: Issues with porting C++ code to a 64-bit platform

#22
post #20

Earlier quoted context omitted.

Actually a 63 bit number and a 1 bit sign flag Not true. Modern architectures use 2s-complement rather than an explicit sign bit to represent integers. If you use a sign bit, there are two different zeros (positive and negative) but the range of positive numbers is exactly as large as the range of negative numbers. With 2s-complement, there's only one zero and the range of negative numbers is larger (by one) than the…

In 2s complement, the most significant bit is the sign bit. In fact all valid C integer representations have a sign bit.

Signed integer representations. Unsigned ints do not, and you're given the full range of the integer as valid data.

Re: Issues with porting C++ code to a 64-bit platform

#23
post #12
post #3

I had issue #2 (varags) bite me once on a C function where a NULL pointer was used as a sentinel. In C++ we normally use '0' as the name of the null pointer, as C's NULL macro ((void*)0) gives compilation errors normally (though it would have worked here). And of course, who knows what the NULL macro is defined to in C++ mode, it could be plain '0' or a compiler-specific type. With varargs '0' simply translates to in…

Huh. I'd always thought C++ shared C's definition of NULL, but looking I see that it doesn't. What a weird thing to change. At least they've added some safety with nullptr_t.

I'm not convinced that the explosion of specialized types benefits anyone but language lawyers. Some of us actually have work to do, and NULL should mean NULL.

Using '0' for null pointers as mpyne suggests is less desirable because it robs the reader of context ("Is this a pointer being compared to 0, or a numeric type?") That could be worked around with Hungarian notation, but some would argue that the cure is worse than the disease.

Re: Issues with porting C++ code to a 64-bit platform

#24

This is great information for anyone making the 32-bit to 64-bit transition, and at this point you really should be viewing 64-bit as your primary platform if you're writing code for x86(amd64) platforms. Just falling back to 32-bit mode with WoW or similar for your target platform is just inexcusable at this point unless you have very specific legacy support issues. As someone who has been stepping away from C/C++ c…

> This is great information for anyone making the 32-bit to 64-bit transition, and at this point you really should be viewing 64-bit as your primary platform if you're writing code for x86(amd64) platforms. Just falling back to 32-bit mode with WoW or similar for your target platform is just inexcusable at this point unless you have very specific legacy support issues.

Eh, unless you absolutely need the addressable memory, there's no real reason to move a legacy codebase to native 64-bit unless the software absolutely needs the RAM.

The general takeaway is that you shouldn't be relying on primitives that aren't underlying OS/implementation safe. Using things like longs(especially if you're targeting both Linux and Windows), and assumed pointer lengths can bite you in the ass if you're not careful(and there is a special circle of hell reserved for people who think bitshifting on a pointer type is fine). A few minutes doing some preventative #defines can save you a world of hurt, especially when porting to the next largest system.

Re: Issues with porting C++ code to a 64-bit platform

#25
post #15

Earlier quoted context omitted.

> 64 bits is 64 bits he said, right... well yes That's the problem right there. 64 bits is not always 64 bits. While a 64 bit int gives you a 64 bit number (Actually a 63 bit number and a 1 bit sign flag). An IEEE double precision float only gives you a 52 bit number, and a separate 11 bit number as an exponent. So the problem is that declaring that 64 bits is 64 bits is actually precisely the issue here.

Actually a 63 bit number and a 1 bit sign flag Not true. Modern architectures use 2s-complement rather than an explicit sign bit to represent integers. If you use a sign bit, there are two different zeros (positive and negative) but the range of positive numbers is exactly as large as the range of negative numbers. With 2s-complement, there's only one zero and the range of negative numbers is larger (by one) than the…

This is a technicality. Leftmost bit still denotes a sign and modulo of the number is still capped at n-1 bits.

Re: Issues with porting C++ code to a 64-bit platform

#26
post #22
post #20

Earlier quoted context omitted.

In 2s complement, the most significant bit is the sign bit. In fact all valid C integer representations have a sign bit.

Signed integer representations. Unsigned ints do not, and you're given the full range of the integer as valid data.

Yes you're right. I should have been more specific that all signed integers have a sign bit.

Re: Issues with porting C++ code to a 64-bit platform

#27
post #12

Earlier quoted context omitted.

Huh. I'd always thought C++ shared C's definition of NULL, but looking I see that it doesn't. What a weird thing to change. At least they've added some safety with nullptr_t.

I'm not convinced that the explosion of specialized types benefits anyone but language lawyers. Some of us actually have work to do, and NULL should mean NULL. Using '0' for null pointers as mpyne suggests is less desirable because it robs the reader of context ("Is this a pointer being compared to 0, or a numeric type?") That could be worked around with Hungarian notation, but some would argue that the cure is worse…

But before nullptr, NULL didn't portably mean "a null pointer". It meant "0", just as if you'd typed in "0" rather than "NULL". The language doesn't really give the library writer much choice in the matter! (Defining NULL as "((void *)0)" would at least give it an inherently pointer type, but it would be terribly inconvenient to use.)

This is the whole reason for nullptr in the first place.

Re: Issues with porting C++ code to a 64-bit platform

#28
post #13

One thing he doesn't mention is "-fPIC", I've been bitten by this bug many times: "please re-compile with PIC enabled and try again"!

Is there any reason that compilers don't somehow fix this thing by default?

They can't - you get this error when trying to link other objects, which are already compiled without position-independent code. So the linker can't really fix this.

Also, if you're not doing dynamic linking, code without -fPIC is generally faster and for use-cases where C (and/or C++) is used that can make a difference.

Re: Issues with porting C++ code to a 64-bit platform

#29
post #20

Earlier quoted context omitted.

Actually a 63 bit number and a 1 bit sign flag Not true. Modern architectures use 2s-complement rather than an explicit sign bit to represent integers. If you use a sign bit, there are two different zeros (positive and negative) but the range of positive numbers is exactly as large as the range of negative numbers. With 2s-complement, there's only one zero and the range of negative numbers is larger (by one) than the…

In 2s complement, the most significant bit is the sign bit. In fact all valid C integer representations have a sign bit.

I think his point is that changing a sign bit doesn't affect the absolute value, just its sign. A sign bit has no value itself - it's just a flag. If the representation has a sign bit, you'd have a negative zero.

But the top bit in 2s complement has a value - it's just a negative one (that's large enough to make any value with it set negative). That's not a sign bit! If you change it, the absolute value most definitely changes, and quite substantially.

Re: Issues with porting C++ code to a 64-bit platform

#30

Earlier quoted context omitted.

Actually a 63 bit number and a 1 bit sign flag Not true. Modern architectures use 2s-complement rather than an explicit sign bit to represent integers. If you use a sign bit, there are two different zeros (positive and negative) but the range of positive numbers is exactly as large as the range of negative numbers. With 2s-complement, there's only one zero and the range of negative numbers is larger (by one) than the…

This is a technicality. Leftmost bit still denotes a sign and modulo of the number is still capped at n-1 bits.

The differences between the representations matter. In 2s complement, -INT_MIN is not INT_MAX; in fact, -INT_MIN is undefined and a C compiler is justified in deleting all your code if you ever cause it to calculate -INT_MIN.

I tell you what: if you think modern architectures use an explicit sign bit to represent integers, how do you explain the fact that INT_MAX+1==-INT_MIN? If there's a sign bit, how could you possibly represent more negative integers than positive integers?

Post reply on HN