# C++预处理及宏定义

# 1.多行宏

#include <iostream>
using namespace std;

#define ABC 1, \
            2, \
            3
int main(int argc, char **argv)
{
    int arr[] = {ABC};
    for(int i=0; i<3; i++) {
        std::cout << arr[i] << std::endl;
    }
#undef ABC

    return 0;
}
/**
 * 1
 * 2
 * 3
 */

# 2.#/##/...符号

  • #将其后面的宏参数进行字符串化操作
#include <iostream>

#define STRINGFI(var) #var

int main(int argc, char **argv)
{
    std::cout << "Hello, " STRINGFI(1123) << std::endl;
    return 0;
    // Hello, 1123
}
  • ##被称为连接符(concatenator),用来将两个Token连接为一个Token。
#include <iostream>

#define CONCAT(a, b) a ## b
#define HEL(a, b)  CONCAT(a, b)

void hel1(void)
{
    std::cout << "hello1" << std::endl;
}

void hel2(void)
{
    std::cout << "hello2" << std::endl;
}

int main(int argc, char **argv)
{
    HEL(hel, 1)();
    HEL(hel, 2)();
    // hello1
    // hello2
    return 0;
}
  • ...在宏中称为Variadic Macro,也就是变参宏
#include<cstdio>
#define LOG_ERR(fmt, ...) printf(fmt, __VA_ARGS__)

int main(int argc, char **argv)
{
    LOG_ERR("%d%d%d%d%s",1,2,3,4, "this");  
    // 1234this
    return 0;
}

# 3.条件宏

#if defined(A)
#elif !definend(B)
#else
...
#endif
  • 是否定义宏 #if defined(A)
  • 没有定义宏 #if !defined(A)

#if支持的条件

  • 整数常数,加减乘除数字运算,大小比较
  • 逻辑运算,&&||

#if defined BUFSIZE && BUFSIZE >= 1024
...
#endif

#if defined (__vax__) || defined (__ns16000__)
...
#endif

示例:

#include <cstdio>
#define LOG_LEVEL 12
#if LOG_LEVEL + 1 >= 14
#define LOG_ERR(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define LOG_ERR(fmt, ...) void(0)
#endif

int main(int argc, char **argv)
{
    LOG_ERR("%d", 12);
    return 0;
}

上面的示例中使用了#define LOG_ERR(fmt, ...) void(0)语句,这个是告诉编译器是空语句,在预处理阶段不会生成任何代码。

使用cmake管理工程时,编译时添加宏,

target_compile_definitions(foo PUBLIC DFOO=1)