How to detect on C++ is windows 32 or 64 bit?
I see a lot of examples in .Net but I need C++. Also IsWow64Process() dosen't works for me, becouse "If the process is running under 32-bit Windows, the value is set to FALSE. If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE"
if I have 32 bit proc under 32 bit OS I have FALSE
if I have 64 bit proc under 64 bit OS I have FALSE
BUT I dont care about process bit I need OS bit
The Win32 API function to detect information about the underlying system is GetNativeSystemInfo. Call the function and read the wProcessorArchitecture member of the SYSTEM_INFO struct that the function populates.
Although it is actually possible to use IsWow64Process to detect this. If you call IsWow64Process and TRUE is returned, then you know that you are running on a 64 bit system. Otherwise, FALSE is returned. And then you just need to test the size of a pointer, for instance. A 32 bit pointer indicates a 32 bit system, and a 64 bit pointer indicates a 64 bit system. In fact, you can probably get the information from a conditional supplied by the compiler, depending on which compiler you use, since the size of the pointer is known at compile time.
Raymond Chen described this approach in a blog article. He helpfully included code which I reproduce here:
BOOL Is64BitWindows()
{
#if defined(_WIN64)
return TRUE; // 64-bit programs run only on Win64
#elif defined(_WIN32)
// 32-bit programs run on both 32-bit and 64-bit Windows
// so must sniff
BOOL f64 = FALSE;
return IsWow64Process(GetCurrentProcess(), &f64) && f64;
#else
return FALSE; // Win64 does not support Win16
#endif
}
GetSystemWow64DirectoryW
Retrieves the path of the system directory used by WOW64. This directory is not present on 32-bit Windows.
An alternative method is to check for the existence of the "Program Files (x86)" root folder on the system partition. It will be present on x64 windows installations, and not on x86 installations.
Related
I have a Windows7 Maximal 64-bit computer with 8 Gb RAM. I have created a Win32 console aplication in MSVC and wrote as follows:
size_t const s_chunkSize = 1024 * 32;
size_t total = 0;
for (;;)
{
if (!::malloc(s_chunkSize))
{
break;
}
total += s_chunkSize;
}
printf("total = %li", total);
// yes, I do not free allocated memory for simplicity
It output me 2111668224 that is below 2Gb. How can I force my program to allocate more that 2Gb? Do I have to change some MSVC project settings? Or do I have to use not malloc but Windows-specific functions? Or do I have to configure Windows somehow?
As explained in the comments, you must use the /LARGEADDRESSAWARE linker flag to enable the use of >2GB of virtual address space on machines that provide it (typically, 32 bit machines with the /3GB flag or 64 bit machines). Notice that doing this requires you to exercise extra care when dealing with pointers ( http://blogs.msdn.com/b/oldnewthing/archive/2004/08/12/213468.aspx and articles linked from there), and won't allow you to access more than 4 GB of virtual address space anyway.
A better solution is to build a 64 bit version of your program: you are no longer restricted to a 32 bit address space, and you avoid the caveats of addresses with the high bit set. Obviously, the downside (beside the porting problems that may arise) is that the generated executable will run only on 64 bit machines.
I need to set #ifdef - checks for conditional compile. I want to automate the process but cannot specify the target OS/machine. Is there some way that the pre-compiler can resolve whether it it is running on 32-bit or 64-bit?
(Explanation) I need to define a type that is 64 bits in size. On 64bit OS it is a long, on most others it is a long long.
I found this answer - is this the correct way to go?
[edit] a handy reference for compiler macros
The only compile check you can do reliably would be sizeof(void*) == 8, true for x64 and false for x86. This is a constexpr and you can pass it to templates but you can forget using ifdef with it. There is no platform-independent way to know the address size of the target architecture (at pre-process time), you will need to ask your IDE for one. The Standard doesn't even have the concept of the address size.
No there is no standard language support for macro to determine if the machine is a 64-bit or 32-bit at preprocessor stage.
In response to your edit, there is a "macro-less for you" way to get a type that is 64 bits.
if you need a type that can hold 64 bits, then #include <cstdint> and use either int64_t or uint64_t. You can also use the Standard Integer Types provided by Boost.
Another option is to use long long. It's technically not part of the C++ standard (it will be in C++0x) but is supported on just about every compiler.
I would look at source code for a cross-platform library. It is a quite large part. Every pair of OS and compiler has own set of definitions. Few libraries You may look at:
http://www.libsdl.org/ \include\SDL_config*.h (few files)
http://qt.nokia.com/ \src\corelib\global\qglobal.h
Boost has absorbed the old Predef project. You'll want the architecture macros, more specifically BOOST_ARCH_X86_32/BOOST_ARCH_X86_64, assuming you only care about x86.
If you need a wider detection (e.g. ARM64), either add the relevant macro's to your check, or check what you actually want to check, e.g.
sizeof(void*) == 8
Well, the answer is clearly going to be OS-specific, so you need to narrow down your requirements.
For example, on Unix uname -a typically gives enough info to distinguish a 32-bit build of the OS from a 64-bit build.
The command can be invoked by your pre-compiler. Depending on its output, compiler flags can be set appropriately.
I would be tempted to hoist the detection out of the code and put that into the Makefile. Then, you can leverage system tools to detect and set the appropriate macro upon which you are switching in your code.
In your Makefile ...
<do stuff to detect and set SUPPORT_XX_BIT to the appropriate value>
gcc myFile.c -D$(SUPPORT_XX_BIT) -o myFile
In your code ...
#if defined(SUPPORT_32_BIT)
...
#elif defined(SUPPORT_64_BIT)
...
#else
#error "Select either 32 or 64 bit option\n"
#endif
Probably the easiest way might be comparing the size of int and long long. You cannot do it in the pre-processor though but you can use it in static_assert.
Edit: WoW all the negative votes. I made my point a bit more clear. Also it appears I should have mentioned 'long long' rather than 'long' because of the way MSVC works.
I searched in web, could not get any program.
I found following links size of machine 64 or 32 bit and processing files in 64 bit machine but developing in 32 bit machine.
Now it is clear that sizeof(int*) is not the way. Because it will return 4/8 based on the architecture of the machine used for compilation. So then how to find it?
Condition: do not use any system/os/library call.
Actually it is a question asked in the interview.
32-bit system address spaces cannot address more than 4gb of memory. Assuming the 64-bit platform has that amount available free (debatable), you could try and allocate more than 4 gig in a single chunk. This will most certainly fail on a 32-bit system.
This is just a thought, and I'll probably be down-voted to hell and back, but it's just a suggestion :)
Compile the program as 64 bit and try if it can be executed on the target machine or not?
What about inline assembly? :)
This is based solely on information read with CPUID instruction. It doesn't matter what OS is used.
#include <iostream>
bool is64Bit()
{
int ExtendedFeatureFlags;
asm ( "mov $0x80000001, %%eax; " // 0x80000001 gets Extended Feature Flags
"cpuid; " // Call CPUID instruction.
"mov %%edx, %0; " // Copy EDX into first output variable.
:"=r"(ExtendedFeatureFlags) // Output variable.
: // No input variables.
:"%eax","%ebx","%ecx","%edx" // Clobbered registers.
);
return ExtendedFeatureFlags & (1<<29);
// If the 29th bit is on, the processor supports 64bit
// extensions.
}
int main()
{
std::cout << "Is 64bit?: " << (is64Bit() ? "YES" : "NO") << std::endl;
return 0;
}
How about making a program that creates a simple.cpp file itself and tries to compile it both ways? :)
I'll be very impressed if you manage to find any way aisde from sizeof(int*) that doesn't use an operating system call. I think that you probably already have as good an answer as they were looking for :p
With C++ an int on a 64 bit machine with a 64 bit compiler should be 64 bits, likewise for a 32 bit machine, so sizeof(int*) should work
The 32-bit environment sets int, long and pointer to 32 bits and generates code that runs on any i386 system.
The 64-bit environment sets int to 32 bits and long and pointer to 64 bits and generates code for AMD's x86-64 architecture.
You can use
#include <stdio.h>
int main(){
long z; printf("Long int size is %i bytes long!\n", sizeof(z)); return 0;
}
and compile with -m32 and -m64 in gcc. If its a 64bit platform the program will run and output will be 8 else program will die.
#include <stdio.h>
int main(void) {
printf("\n The Processor in this machine is %lu Bit Machine", sizeof(void *));
return 0;
}
How about using the uname system call on POSIX complaint systems: http://linux.die.net/man/2/uname
The required information will be in the machine field.
I have just been given the task of updating a legacy application from 32-bit to 64-bit. While reviewing the extent of the task, I discovered the following definition immediately before the inclusion of external (eg. platform) headers:
#define POINTER_32
I cannot find what uses this definition or what effect it has, but it looks like the kind of thing that will be directly relevant to my task!
What is it for? What uses it? Will it be safe to remove it immediately (I presume it will be necessary to remove it in the long run)?
This is using MS VC++ 2008, soon to be 2010.
This is a macro that's normally declared in a Windows SDK header, BaseTsd.h header file. When compiling in 32-bit mode, it is defined as you showed. When compiling in 64-bit mode it is defined as
#define POINTER_32 __ptr32
which is an MSVC compiler extension to declare 32-bit pointers in a 64-bit code model. There's also a 64-bit flavor for 32-bit code:
#define POINTER_64 __ptr64
You'd use it if you write a 64-bit program and need to interop with structures that are used by 32-bit code in another process. For example:
typedef struct _SCSI_PASS_THROUGH_DIRECT32 {
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
VOID * POINTER_32 DataBuffer; // <== here
ULONG SenseInfoOffset;
UCHAR Cdb[16];
}SCSI_PASS_THROUGH_DIRECT32, *PSCSI_PASS_THROUGH_DIRECT32;
Used to get around the Warning C4244 . Provides a 32-bit pointer in both 32-bit and 64-bit models
My guest is that it was originally created for VLM (Very Large Memory) in Alpha AXP, because Windows NT for Alpha is the first Windows with some 64-bit support. The OS is still 32-bit but it has the VLM API for applications to allocate large 64-bit memory if necessary, hence there must be some way to declare both 32 and 64-bit pointers in the same program
VLM returns POINTER_64 that the app has to store. POINTER_32/__ptr32 are used by default, and POINTER_64/__ptr64 will be used in 64-bit handling code
You can still even see some relics of AXP in Windows documentation and header files related to POINTER_32
POINTER_32 is defined in Ntdef.h and Winnt.h.
#ifdef (__AXP64__)
#define POINTER_32 _ptr32
#else
#define POINTER_32
#endif
Warning C4244
__AXP64__ is meant for Alpha AXP. You can also find lots of other references to Alpha AXP in Ntdef.h and Winnt.h even though Windows no longer runs on that platform
Because of this there are also POINTER_SIGNED and POINTER_UNSIGNED macros to specify how the 32-bit address is extended to the 64-bit one. They'll be expanded to __sptr and __uptr
Another usage would be for 32-bit pointers when disabling LARGEADDRESSAWARE in a 64-bit application
It's exactly the same as x32 ABI in Linux where long and pointers are 32-bit wide
By default, 64-bit Microsoft Windows-based applications have a user-mode address space of several terabytes. For precise values, see Memory Limits for Windows and Windows Server Releases. However, applications can specify that the system should allocate all memory for the application below 2 gigabytes. This feature is beneficial for 64-bit applications if the following conditions are true:
A 2 GB address space is sufficient.
The code has many pointer truncation warnings.
Pointers and integers are freely mixed.
The code has polymorphism using 32-bit data types.
All pointers are still 64-bit pointers, but the system ensures that every memory allocation occurs below the 2 GB limit, so that if the application truncates a pointer, no significant data is lost. Pointers can be truncated to 32-bit values, then extended to 64-bit values by either sign extension or zero extension.
Virtual Address Space
When setting /LARGEADDRESSAWARE:NO the size of pointers are still 64-bit wide even though the high 32 bits has no significant values. Therefore to save memory for the pointer we must declare them as POINTER_32
See How to detect X32 on Windows?
In a C++ function I need the compiler to choose a different block if it is compiling for a 64 bit architecture.
I know a way to do it for MSVC++ and g++, so I'll post it as an answer. However I would like to know if there is a better way (more elegant that would work for all compilers/all 64 bits architectures). If there is not a better way, what other predefined macros should I look for in order to be compatible with other compiler/architectures?
An architecture-independent way to detect 32-bit and 64-bit builds in C and C++ looks like this:
// C
#include <stdint.h>
// C++
#include <cstdint>
#if INTPTR_MAX == INT64_MAX
// 64-bit
#elif INTPTR_MAX == INT32_MAX
// 32-bit
#else
#error Unknown pointer size or missing size macros!
#endif
This works for MSVC++ and g++:
#if defined(_M_X64) || defined(__amd64__)
// code...
#endif
Why are you choosing one block over the other? If your decision is based on the size of a pointer, use sizeof(void*) == 8. If your decision is based on the size of an integer, use sizeof(int) == 8.
My point is that the name of the architecture itself should rarely make any difference. You check only what you need to check, for the purposes of what you are going to do. Your question does not cover very clearly what your purpose of the check is. What you are asking is akin to trying to determine if DirectX is installed by querying the version of Windows. You have more portable and generic tools at your disposal.
Raymond covers this.
If you're compiling for the Windows platform, you should use:
#ifdef _WIN64
The MSVC compiler defines that for both x64 and ia64 platforms (you don't want to cut out that market, do you?). I'm not sure if gcc does the same - but it should if it doesn't.
An alternative is
#ifdef WIN64
which has a subtle difference. WIN64 (without the leading underscore) is defined by the SDK (or the build configuration). Since this is defined by the SDK/build config, it should work just as well with gcc.
#ifdef _LP64
Works on both platforms
Here's a good overview for Mac OS X:
http://developer.apple.com/documentation/Darwin/Conceptual/64bitPorting
If your using Windows, your probably better to get the "PROCESSOR_ARCHITECTURE" environment variable from the registry because sizeof(PVOID) will equal 4 if its a 32bit process running on a 64bit operating system (aka WOW64):
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\CurrentControlSet\\Control\\Session Manager\\Environment"), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
LPSTR szArch = new CHAR[100];
ZeroMemory(szArch, 100);
if (RegQueryValueEx(hKey, _T("PROCESSOR_ARCHITECTURE"), NULL, NULL, (LPBYTE)szArch, &dwSize) == ERROR_SUCCESS) {
if (strcmp(szArch, "AMD64") == 0)
this->nArchitecture = 64;
else
this->nArchitecture = 32;
} else {
this->nArchitecture = (sizeof(PVOID) == 4 ? 32 : 64);
}
RegCloseKey(hKey);
}