Converting 32-bit Application Into 64-bit Application in C
Solution 1
- Find out who wrote it. Are they an idiot? Are they you from a few years ago? Can you ask them questions? Are they familiar with the existence of multiple platforms and systems? Knowing the mind-set of the author(s) of the program will help you understand problems when you run into them.
- Get a 64-bit machine/build environment up and running.
- Replace long with int. Be perfectly aware that
LONG
is notlong
. - Replace
(int)&x
casts and typing withintptr_t
and(unsigned int)&x
withuintptr_t
- Audit anything that relies on casting structures to
char*
to do pointer arithmetic with it. - Regex search for \<4\> in case you assumed
4 = sizeof(void*)
- Be patient. When you find a problem, look elsewhere if the same problem exists, and wrap the solution in a macro.
- Try not to use
#ifdef RUN64
or anything similar. You'll regret it if 128-bit platforms ever go into vogue. - Encapsulate all of your changes in terms of some centralized macros that'll hide the portability differences elsewhere in your program.
- Use a coverage tester to help make sure you've covered everything (if appropriate)
EDIT added uintptr_t
note as suggested by comment.
Solution 2
One potential problem not already mentioned is that if your app reads or writes binary data from disk (e.g., read an array of structs using fread
), you are going to have to check very carefully and perhaps wind up having two readers: one for legacy files and one for 64-bit files. Or, if you are careful to use types like uint32_t
and so on from the <stdint.h>
header file, you can redefine your structs to be bit-for-bit compatible. In any case, binary I/O is a thing to watch out for.
Solution 3
This really depends on the application and how it has been coded. Some code can just be recompiled with a 64-bit compiler and it will just work, but usually this only happens if the code has been designed with portability in mind.
If the code has a lot of assumptions about the size of native types and pointers, if it has a lot of bit packing hacks or of it talks to an external process using a byte specified protocol but using some assumptions about the size of native types then it may require some, or a lot, of work to get a clean compile.
Pretty much every cast and compiler warning is a red flag that needs checking out. If the code wasn't "warning clean" to start with then that is also a sign that a lot of work may be required.
Solution 4
If you used the correct types for your values - eg. size_t
, ptrdiff_t
, uintptr_t
, the fixed sized int types from stdint.h
where appropriate - and did not hardcode value sizes, your code should work out of the box.
Solution 5
The two major differences between 32-bit and 64-bit programming in C are sizeof(void*)
and sizeof(long)
. The major problem that you will have is that the most Unix systems use the I32LP64 standard which defines a long as 64 bits and Win64 uses the IL32LLP64 standard which defines a long as 32 bits. If you need to support cross-platform compilation, you may want to use a set of architecture based typedefs for 32-bit and 64-bit integers to ensure that all code will behave consistently. This is provided as part of stdint.h as part of the C99 standard. If you are not using a C99 compiler, you may need to roll your own equivalent
As noted elsewhere the primary concerns for conversion will be code that assume sizeof(int) == sizeof(long) == sizeof(void*)
, code to support data that has been written to disk and code for cross platform IPC.
For a good review of the history behind this, take a look at this article from ACM Queue.
Admin
Updated on July 07, 2021Comments
-
Admin almost 3 years
I am presently working on converting a 32-bit application into a 64-bit application in C. This application is currently working on x86 architecture (Windows, osx, Unix, Linux). So, before starting coding, I wanted to know what do I need to consider while converting the application.
-
Jonathan Leffler over 15 yearsUse uintptr_t instead of intptr_t. You don't need signs on addresses.
-
Christoph over 15 years'C99 is available more places than it is used.' - With the standard being TEN YEARS OLD now, about freakin' time! But gcc support is still incomplete... ps: fixed intptr_t -> uintptr_t
-
Admin over 15 years@Darron: I find that warnings issued by PC-lint (from Gimpel Software) are cryptic. My suggestion is to use Splint (splint.org).
-
geocar over 15 yearsMost people don't perform manipulations on the casted values; they're usually just used to copy some value into a callback, so intptr_t is fine. Although I agree if the difference mattered to the code, it would be a point of interest.
-
Darron over 15 yearsI actually haven't used Gimpel lint for years, as I've moved to the Java world. I'll keep Splint in mind if I end up back in C/C++ territory.
-
QuantumMechanic almost 12 yearsActually,
long
is generally the problem, since on Windowslong
stays at 32 bits but on Unixlong
goes from 32 bits to 64 bits.