Detect Windows or Linux in C, C++
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.
How do I check OS with a preprocessor directive?
The Predefined Macros for OS site has a very complete list of checks. Here are a few of them, with links to where they're found:
Windows
_WIN32
Both 32 bit and 64 bit_WIN64
64 bit only__CYGWIN__
Unix (Linux, *BSD, but not Mac OS X)
See this related question on some of the pitfalls of using this check.
unix
__unix
__unix__
Mac OS X
__APPLE__
Also used for classic__MACH__
Both are defined; checking for either should work.
Linux
__linux__
linux
Obsolete (not POSIX compliant)__linux
Obsolete (not POSIX compliant)
FreeBSD
__FreeBSD__
Android
__ANDROID__
Determine if Linux or Windows in C++
Use:
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
static const std::string slash="\\";
#else
static const std::string slash="/";
#endif
BTW, you can still safely use this slash "/" on Windows as windows understands this perfectly. So just sticking with "/" slash would solve problems for all OSes even like OpenVMS where path is foo:[bar.bee]test.ext
can be represented as /foo/bar/bee/test.ext
.
How to detect reliably Mac OS X, iOS, Linux, Windows in C preprocessor?
There are predefined macros that are used by most compilers, you can find the list here. GCC compiler predefined macros can be found here.
Here is an example for gcc:
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
//define something for Windows (32-bit and 64-bit, this part is common)
#ifdef _WIN64
//define something for Windows (64-bit only)
#else
//define something for Windows (32-bit only)
#endif
#elif __APPLE__
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR
// iOS, tvOS, or watchOS Simulator
#elif TARGET_OS_MACCATALYST
// Mac's Catalyst (ports iOS API into Mac, like UIKit).
#elif TARGET_OS_IPHONE
// iOS, tvOS, or watchOS device
#elif TARGET_OS_MAC
// Other kinds of Apple platforms
#else
# error "Unknown Apple platform"
#endif
#elif __ANDROID__
// Below __linux__ check should be enough to handle Android,
// but something may be unique to Android.
#elif __linux__
// linux
#elif __unix__ // all unices not caught above
// Unix
#elif defined(_POSIX_VERSION)
// POSIX
#else
# error "Unknown compiler"
#endif
The defined macros depend on the compiler that you are going to use.
The _WIN64
#ifdef
can be nested into the _WIN32
#ifdef
because _WIN32
is even defined when targeting the Windows x64 version. This prevents code duplication if some header includes are common to both
(also WIN32
without underscore allows IDE to highlight the right partition of code).
Autodetection of OS in C/C++
I have used below code in past for checking between linux and windows
#include<stdio.h>
int main(int argc, char *argv[])
{
#ifdef _WIN32
printf("in Windows");
#endif
#ifdef linux
printf("In Linux");
#endif
return 0;
}
Usually all toolchain has their own predefined macros so you need to use those macros to detect which os is this.
List of such predefined macros.
http://sourceforge.net/p/predef/wiki/OperatingSystems/
Yes as a side note, Here detection of OS is happened using compile time macros. So according to toolchain respective macro's defination will go in build.
To detect OS version in runtime, like in java we do
System.getProperty("os.name")
Same way in C/C++ we do not have any API.
In POSIX systems using 'uname' we can get OS name.
C++ compiling on Windows and Linux: ifdef switch
use:
#ifdef __linux__
//linux code goes here
#elif _WIN32
// windows code goes here
#else
#endif
How do I know if a C program will written on Linux will work elsewhere
Well, this is kind of simple: Your program will work on Windows as long as it only uses two things:
The C standard library, as described in the C standard. See e.g. n1570.pdf, the latest draft version that's very close to the actual standard. Note that a lot of C standard libraries come with all sorts of extensions, of course you can't use these. If in doubt, compile e.g. with the
-std=c11
option (gcc
orclang
) which should hide all declarations for extensions.There's an additional pitfall here: Microsoft's implementation of the C standard isn't complete. It depends on your compiler which C standard library is actually linked, in case of
MinGW
, it's the very oldmsvcrt.dll
that only conforms to C89, so you might want to read an older standard instead for which functions you can use, e.g. here's a description of the standard library in C89 With Microsoft's C compilers, you get different levels of C99 support also in the standard libraries (they link their own runtime DLLs), depending on the version.Third party libraries that are available for Windows, like e.g.
SDL
,GTK+
, etc.
By using open
, creat
, close
, read
, write
etc., you're using extensions specified in POSIX. Some of the POSIX functions are available on Windows, some are slightly different, some are just missing. You better shouldn't use these if you want to stay portable to Windows. The exception to this rule is if you plan to compile your code with Cygwin, which is a complete POSIX compatibility layer for Windows.
As per IanAbbott's comment, it's also crucial to use integer types correctly and not implicitly assume things like "a long
has 64 bits" or "an int
can hold a pointer", which are wrong in the general case. Always use the <stdint.h>
types for fixed widths, uintptr_t
for pointer values, size_t
for object sizes, and so on.
Although not directly related to your question: For most non-trivial programs, you will sooner or later need to use some platform-specific functionality. Often, there are libraries abstracting this away, like e.g. if you need to handle I/O events efficiently, instead of using epoll
on Linux, kqueue
on FreeBSD, IO completion ports
on Windows and so on, you could just use libevent
. But in case you don't find such a library, here's a tip:
Clearly separate platform-specific code into its own modules (translation units). This way, the work for porting the whole thing to a different platform gets significantly smaller.
Related Topics
Changing the Current Directory in Linux Using C++
Hide or Crop Overlapping Text in Qlabel
When Are Static and Global Variables Initialized
How to Explain Undefined Behavior to Know-It-All Newbies
Checking for Null Pointer in C/C++
Redirecting Cout to a Console in Windows
Why Does Long Long N = 2000*2000*2000*2000; Overflow
Why Does Gcc Compiler Output Pow(10,2) as 99 Not 100
How to Open an .Exe from Another C++ .Exe
Effective C++ Item 23 Prefer Non-Member Non-Friend Functions to Member Functions
How to Compile SQLite with Icu
Why Does C++ Need the Scope Resolution Operator
C++ - Enum VS. Const VS. #Define
How to Implement Multithread Safe Singleton in C++11 Without Using <Mutex>
Does "Const" Just Mean Read-Only or Something More