0

I‘m wondering what would be the simplest way to determine if the current assembly (specifically: programmatically check if the program itself) is 32 or 64 bit code.

Current example: I‘m building a C++ app on Windows/VS that is built as a x86 and as a x64 executable and distributed seperately.

Within the program there is a routine where I have to check what version is currently running (the program has to become aware of it‘s own target, so to speak).

I started going nuts with a lot of calls to the Win32 API, but all of this is very cumbersome and basically just reflecting how the OS executes the program. I‘m sure there has to be a more elegant way that I‘m not aware of? How would you handle this?

Thanks!

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
loopend
  • 69
  • 6
  • If it is your code, you must know how it was built, and can set a flag of some sort in the code. –  Jan 31 '19 at 21:48
  • You could check `sizeof(int*)` – Justin Jan 31 '19 at 21:48
  • @NeilButterworth you‘re right as this would be a simple option - however I was looking for a generic way as a check (meaning: same code for both platform builts) – loopend Jan 31 '19 at 21:49
  • Related, possible duplicate: https://stackoverflow.com/q/1505582/1896169 – Justin Jan 31 '19 at 21:50
  • Related blog post: https://blogs.msdn.microsoft.com/oldnewthing/20060906-07/?p=29843 – Justin Jan 31 '19 at 21:51
  • @loopend the `sizeof()` trick would work in both builds. `sizeof()` any pointer type is 4 in a 32bit build, and 8 in a 64bit build. The real question is - why do you need to know this? The Win32 API exists in both 32bit and 64bit flavors, and you don't need to adjust your code to use one flavor vs the other. If you have to make adjustments to code based on architecture, you are probably doing something wrong. – Remy Lebeau Jan 31 '19 at 21:52
  • @RemyLebeau thanks, this makes sense and seems pretty solid! Regarding the code adjustments: You‘re right, I don’t really adjust anything - I wrote a simple Bootstrapper-Builder in C++ to deploy my C#-applications incl. prereqs and wanted to explicitly inform the user in the case he‘s unintentionally running the 32bit version on a 64bit system as this can be a unnecessary perf impact for the db building routine – loopend Jan 31 '19 at 22:01
  • 1
    @loopend in that situation, it is not enough to just detect whether your app is running as a 32bit build. Since 64bit systems can run 32bit apps, you need to detect if your app is specifically running as a 32bit process on a 64bit system (inside the WOW64 emulator) vs natively as a 32bit process on a 32bit system. Use [`IsWow64Process()`](https://learn.microsoft.com/en-us/windows/desktop/api/wow64apiset/nf-wow64apiset-iswow64process) for that check. – Remy Lebeau Jan 31 '19 at 22:17
  • If you actually meant *assembly language*, not a .NET assembly, see [x86-32 / x86-64 polyglot machine-code fragment that detects 64bit mode at run-time?](//stackoverflow.com/q/38063529). It takes 4 bytes of machine code to write a function that returns 0 for 64-bit or 1 for 32-bit. (With a byte that decodes as `inc eax` or as a no-effect REX.W=0 prefix for a `ret` instruction. But if you can decide at compile time, that's obviously much better to let the compiler optimize away. You can normally use the C preprocessor for this. – Peter Cordes Feb 01 '19 at 01:50

2 Answers2

3
template<std::size_t n>
constexpr bool Am_I_bit(){
  return (sizeof(void*)*CHAR_BIT)==n;
}

constexpr bool I_am_32_bit(){
  return Am_I_bit<32>();
}

constexpr bool I_am_64_bit(){
  return Am_I_bit<64>();
}

Will fail on some ridiculously obscure platforms, but you aren't building those.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • Thanks, this seems solid enough! – loopend Jan 31 '19 at 22:02
  • 1
    ILP32 ABIs in 64-bit mode are one case where this will fail. [Linux x32](https://en.wikipedia.org/wiki/X32_ABI) for x86-64, and [AArch64-ILP32](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0490a/ar01s01.html) – Peter Cordes Feb 01 '19 at 01:52
1
inline bool is_32bit () { return sizeof (void *) <= 4; )

I dont see the need for all those templates - this will get inlined anyway if you put it in a header file.

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • You need to declare it `inline` to put it in a header, but yes this is fine-ish. 32-bit word-addressable DSP architectures with 32-bit `char` will have `sizeof(void*) == 1`, but that's fine unless there are any 64-bit DSP architectures with 32-bit words that you need to detect as 64-bit. – Peter Cordes Feb 01 '19 at 01:54