宏定义与C语言跨平台问题

背景知识

C/C++ 通常使用宏来做跨平台的功能,这个功能又依赖于你系统上安装的编译器内置的宏。 比如说我在一台 linux 主机上可以看到如下宏。

gcc -dM -E -x c /dev/null | grep -i linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

同样的命令我在 mac 上就不会看到 linux 系统相关的宏定义。

gcc -dM -E -x c /dev/null | grep -i linux

但是可以看到 mac 相关的宏定义。

gcc -dM -E -x c /dev/null | grep -i __APPLE__
#define __APPLE__ 1

C语言跨平台程序例子

因为编译器知道它现在运行在哪个系统上,编译器又通过宏把这个信息告诉了程序员;所以程序员只要检查对应平台的宏是否存在,然后执行相应的代码就行了。

#include <stdio.h>

int main(int argc, char **argv)
{
#ifdef __APPLE__
    printf("runing in mac os .");
#elif __linux__
    printf("running in linux os .");
#endif
    return 0;
}
  1. 在 linux 下编译运行的效果如下:
gcc main.c && ./a.out

running in linux os .
  1. 在 mac 下编译运行的效果如下:
gcc main.c && ./a.out

runing in mac os 

自定义宏

我们不只是能使用编译器已经定义好的宏,还能把我们定义的宏告诉编译器;下面定义一下叫 "_EXAMPLE_AGE" 的宏,默认值是 100 ,当然我们可以告诉编译器覆盖这个值。

#include <stdio.h>

#ifndef _EXAMPLE_AGE
/* 如果没有定义 _EXAMPLE_AGE 这个宏就给一个默认值 100
 * 上面说的“没有定义”其实就是说的编译里 gcc 有没有加上对应的宏定义
 */
#define _EXAMPLE_AGE 100
#endif

int main(int argc, char **argv)
{
    printf("_EXAMPLE_AGE =  %d \n", _EXAMPLE_AGE);
    return 0;
}

当我们不告诉编译器宏的值时,编译器会使用我们定义的默认值。

gcc main.c && ./a.out

_EXAMPLE_AGE =  100 

当我们告诉编译器宏的值是多少时,默认值就被覆盖。

gcc -D_EXAMPLE_AGE=10086 main.c && ./a.out
_EXAMPLE_AGE =  10086