Yes, this is possible.
However, understand that this is not a change as simple as it seems. 32-bit libraries expect you to pass arguments to records in a given format, and that pointers are 4 bytes. The 64-bits use another incompatible shape and the 8-byte pointers. If you are going to use 4-byte pointers and all the rest of the resources equal to what it would be in 64-bits, neither version of the library will be compatible with your program. This basically means that you will need to compile all of the libraries you will use in this format.
Another problem is in the kernel. When making a system call , arguments are also passed differently. Then you will also need special kernel support to run such a program.
This is implemented as a new architecture, the x32:
To compile a program in x32 mode, you will need a fairly modern linux environment:
- Linux 64-bit version 3.4 compiled with the CONFIG_X86_X32 option.
- GLIBC 2.16
- GCC 4.7
- Binutils 2.22
My default ubuntu installation comes with these requirements. Compiling a program in x32 mode is simple: add the flag
-mx32 to gcc. I was able to run compiled programs without any additional procedure and looking at the generated assembly makes it clear that 64-bit registers are used, even with 32-bit pointers.
Since it is a relatively new feature (integrated with the kernel at the end of 2011) and little used (ie little tested in production), it is possible that minor problems can be found.
If you do not want to change architecture and prefer something more "stable", another option would be to change all pointers to
uint32_t and do a conversion whenever necessary. There is no loss of performance since this conversion does not generate instructions. However there is the problem of the pointer pointing to something beyond the 4GB. This will happen, for example, for all the pointers of the stack, since the stack starts at the end of the process virtual memory.