Detect Windows or Linux in C, C++ [duplicate]

Solution 1:

It's generally done like this (more or less):

#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#define DIV 1048576 
#define WIDTH 7
#endif

#ifdef linux
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#endif


int main(int argc, char *argv[]) 
{
#ifdef _WIN32
MEMORYSTATUSEX statex;
    statex.dwLength = sizeof (statex);
    GlobalMemoryStatusEx (&statex);

    _tprintf (TEXT("There is  %*ld %% of memory in use.\n"),
            WIDTH, statex.dwMemoryLoad);
#endif

#ifdef linux
char cmd[30];
int flag = 0;   
FILE *fp;
char line[130];     
int TotalMem, TotalFree, TotalUsed;

flag=0;
memcpy (cmd,"\0",30);
sprintf(cmd,"free -t -m|grep Total");          
fp = popen(cmd, "r");       
while ( fgets( line, sizeof line, fp))
{   
    flag++;
    sscanf(line,"%*s %d %d %d",&TotalMem, &TotalUsed, &TotalFree);
}
pclose(fp); 

if(flag)
    printf("TotalMem:%d -- TotalUsed:%d -- TotalFree:%d\n",TotalMem,TotalUsed,TotalFree);
else 
    printf("not found\n");
#endif

    return 0;
}

This way, only code for linux will be compiled while on a linux platform, and only windows code will be compiled on a windows platform.

Solution 2:

You should use the same #ifdef instead of if(OS_Windows) logic in your code:

#ifdef __unix__         
...
#elif defined(_WIN32) || defined(WIN32) 

#define OS_Windows

#endif

int main(int argc, char *argv[]) 
{
#ifdef OS_Windows
 /* Windows code */
#else
 /* GNU/Linux code */
#endif    
}

Solution 3:

I see a lot of varying solutions here, which makes me uncomfortable... What if they work on Linux but not Windows or on Windows but not Linux? What if they only work on some compilers? Etc.

So I found this link, which I like: https://web.archive.org/web/20191012035921/http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system

It looks like these are best (using #ifdef, #endif, etc.):

  • _WIN32 for Windows 32 bit
  • _WIN64 for Windows 64 bit
  • __unix__ for Unix

Solution 4:

You are confusing variables (which exist in run-time) with preprocessor symbols (which only exist during compilation).

After you do something like #define OS_Windows 1, you can't use the symbol OS_Windows as a variable and put it inside if()s... I mean, you can, but it will be expanded during compilation to if (1).

For a cross-platform project, you have to use #if or #ifdef to make sure that the compiler chooses a correct part of code for a given OS and compiles only that.

Something like:

void openWindow() {
#if OS_Windows
    // windows-specific code goes here
#else
    // linux-specific code
#endif
}