C/C++宏定义

基础知识

  1. 在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组
  2. ##是一种分隔连接方式,它的作用是先分隔,然后进行强制连接
  • 宏中遇到#或##时就不会再展开宏中嵌套的宏了
  1. 宏定义中do{ }while(0)
  • 空的宏定义避免warning:

  • 存在一个独立的block,可以用来进行变量定义,进行比较复杂的实现。

  • 如果出现在判断语句过后的宏,这样可以保证作为一个整体来是实现

  • 在把宏引入代码中,会多出一个分号,从而会报错。这对这一点,可以将if和else语句用{}括起来,可以避免分号错误

#include <stdio.h>
#define MACRO_FUNC(cond) \
  do { \
    if (cond) \
      (void)0;\
    else \
      AssertFailure_(__func__, __FILE__, __LINE__, #cond);\
  } while (0)

void AssertFailure_(const char *func, const char *file, int line,const char *cond_str){
	printf("%s,%s,%d,%s\n",func,file,line,cond_str);
}
int main()
{
    if(2 > 1)
        MACRO_FUNC(0);
    else
        printf("Fail.\n");
    return 0;
}

main,macrot.cpp,17,0

#include <stdio.h>
void action1(){
    printf("======\n");
}

void action2(){
    printf("++++++\n");
}
#define foo(x) \
    action1(); \
    action2();

#define switch_(x,y) {int tmp; tmp=x;x=y;y=tmp;}

int main(){
    if(true)
        for (int i = 0; i < 2; ++i)
            foo();
    int x = 3;
    int y = 4;
    if(x>y){
        switch_(x,y);
    }
    else{
        printf("exp3\n");
    }
    
    return 0;
}

综合知识

例一:基本宏函数替换

#include<stdio.h> 
#include <cassert>
#include <iostream>
#include <string>
#define DEBUG_PRINT(msg)    do{printf("%s - %s - line:%d, file:%s", __DATE__, __TIME__, __LINE__, __FILE__);printf(msg);}while(0)
using std::string;

class LogMessage {
 public:
  LogMessage(const string &type) : fatal_(type == "FATAL") {
    std::cerr << type << ": ";
  }
  ~LogMessage() {
    std::cerr << std::endl;
    printf("12349999999");
    if(fatal_)
      exit(1);
  }
  std::ostream &stream() { return std::cerr; }

 private:
  bool fatal_;
};
#define CHECK(x) FstCheck(static_cast<bool>(x), #x, __FILE__, __LINE__)
#define LOG(type) LogMessage(#type).stream()


inline void FstCheck(bool x, const char* expr,
                const char *file, int line) {
  if (!x) {
    LOG(FATAL) << "Check failed: \"" << expr
               << "\" file: " << file
               << " line: " << line;
  }
}

#define TOW      (2) 
#define MUL(a,b) (a*b) 


int main() 
{ 
    CHECK(1);  
    printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW)); 
    printf("%d*%d=%d\n", (2), (2), ((2)*(2))); 
    return 0; 
} 

例二:宏函数包装一层可以实现宏函数替换,并查看中间替换结果

#include<stdio.h> 
#include <cassert>
#include <iostream>
#include <string>

using std::string;


template <typename T>
class FlagRegister {
 public:
  static FlagRegister<T> *GetRegister() {
    static auto reg = new FlagRegister<T>;
    return reg;
  }
};

template <typename T>
struct FlagDescription {
  FlagDescription(T *addr, const char *doc, const char *type,
		  const char *file, const T val)
      : address(addr),
    doc_string(doc),
    type_name(type),
    file_name(file),
    default_value(val) {}

  T *address;
  const char *doc_string;
  const char *type_name;
  const char *file_name;
  const T default_value;
};

template <typename T>
class FlagRegisterer {
 public:
  FlagRegisterer(const string &name, const FlagDescription<T> &desc) {
    auto registr = FlagRegister<T>::GetRegister();
    registr->SetDescription(name, desc);
  }

 private:
  FlagRegisterer(const FlagRegisterer &) = delete;
  FlagRegisterer &operator=(const FlagRegisterer &) = delete;
};




#define DEFINE_VAR(type, name, value, doc)                                \
  type FLAGS_ ## name = value;                                            \
  static FlagRegisterer<type>                                             \
  name ## _flags_registerer(#name, FlagDescription<type>(&FLAGS_ ## name, \
                                                         doc,             \
                                                         #type,           \
                                                         __FILE__,        \
                                                         value))

#define DEFINE_bool(name, value, doc) DEFINE_VAR(bool, name, value, doc)

#define  _STR(x)  #x
#define  STR(x)  _STR(x)
int main() 
{ 
    printf(STR(DEFINE_VAR(bool,keep_isymbols, false, "Store input label symbol table with FST")));
    return 0; 
} 

输出

bool FLAGS_keep_isymbols = false; static FlagRegisterer keep_isymbols_flags_registerer(“keep_isymbols”, FlagDescription(&FLAGS_keep_isymbols, “Store input label symbol table with FST”, “bool”, “tdefine.cc”, false))

例三:检查指针

#include <iostream>
using namespace std;

#define CHECK_NOTNULL(val) \
    CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))

template <typename T>
T* CheckNotNull(const char* file, int line, const char *names, T* ptr)
{
    if (ptr == NULL)
    {
        cout << file << " " << line << ":" << names << endl;
    }
    return ptr;
}

int main(){
    int *p;
    *p = 5;
    CHECK_NOTNULL(p);
    int *q=CHECK_NOTNULL(p);
    q=NULL;
    CHECK_NOTNULL(q);
    return 0;
}

例四: 模版嵌入
Arctest.cpp

#include<iostream>
#include <string>
#include "generic-register.h"

namespace fst {
    template <class Arc>
    class Fst;
    struct FstReadOptions;
    template <class Arc>
    struct FstRegisterEntry {
        using Reader = Fst<Arc> *(*)(std::istream &istrm, const FstReadOptions &opts);
        using Converter = Fst<Arc> *(*)(const Fst<Arc> &fst);

        Reader reader;
        Converter converter;

        explicit FstRegisterEntry(Reader reader = nullptr,
                                  Converter converter = nullptr)
                : reader(reader), converter(converter) {}
    };

    template <class Arc>
    class FstRegister
            : public GenericRegister<string, FstRegisterEntry<Arc>, FstRegister<Arc>> {
    public:
        using Reader = typename FstRegisterEntry<Arc>::Reader;
        using Converter = typename FstRegisterEntry<Arc>::Converter;

        const Reader GetReader(const string &type) const {
            return this->GetEntry(type).reader;
        }

        const Converter GetConverter(const string &type) const {
            return this->GetEntry(type).converter;
        }

    protected:
        string ConvertKeyToSoFilename(const string &key) const override {
            string legal_type(key);
            return legal_type + "-fst.so";
        }
    };

    template <class FST>
    class FstRegisterer : public GenericRegisterer<FstRegister<typename FST::Arc>> {
    public:
        using Arc = typename FST::Arc;
        using Entry = typename FstRegister<Arc>::Entry;
        using Reader = typename FstRegister<Arc>::Reader;

        FstRegisterer()
                : GenericRegisterer<FstRegister<typename FST::Arc>>(FST().Type(),
                                                                    BuildEntry()) {}

    private:
        static Entry BuildEntry() {
            FST *(*reader)(std::istream & strm, const FstReadOptions &opts) =
            &FST::Read;
            return Entry(reinterpret_cast<Reader>(reader),
                         &FstRegisterer<FST>::Convert);
        }

        static Fst<Arc> *Convert(const Fst<Arc> &fst) { return new FST(fst); }
    };

#define REGISTER_FST(FST, Arc) \
  static fst::FstRegisterer<FST<Arc>> FST##_##Arc##_registerer

    template <class Arc>
    Fst<Arc> *Convert(const Fst<Arc> &fst, const string &fst_type) {
        auto *reg = FstRegister<Arc>::GetRegister();
        const auto converter = reg->GetConverter(fst_type);
        if (!converter) {
            cout << "Fst::Convert: Unknown FST type " << fst_type << " (arc type "
                       << Arc::Type() << ")";
            return nullptr;
        }
        return converter(fst);
    }

}

#define  _STR(x)  #x
#define  STR(x)  _STR(x)
int main()
{
    std::cout << STR(REGISTER_FST(A,B)) << std::endl;
    return 0;
}

register.h

#include <string>
namespace fst {

    template <class Arc>
    class Fst;

    struct FstReadOptions;
    template <class Arc>
    struct FstRegisterEntry {
        using Reader = Fst<Arc> *(*)(std::istream &istrm, const FstReadOptions &opts);
        using Converter = Fst<Arc> *(*)(const Fst<Arc> &fst);

        Reader reader;
        Converter converter;

        explicit FstRegisterEntry(Reader reader = nullptr,
                                  Converter converter = nullptr)
                : reader(reader), converter(converter) {}
    };

    template <class Arc>
    class FstRegister
            : public GenericRegister<string, FstRegisterEntry<Arc>, FstRegister<Arc>> {
    public:
        using Reader = typename FstRegisterEntry<Arc>::Reader;
        using Converter = typename FstRegisterEntry<Arc>::Converter;

        const Reader GetReader(const string &type) const {
            return this->GetEntry(type).reader;
        }

        const Converter GetConverter(const string &type) const {
            return this->GetEntry(type).converter;
        }

    protected:
        string ConvertKeyToSoFilename(const string &key) const override {
            string legal_type(key);
            ConvertToLegalCSymbol(&legal_type);
            return legal_type + "-fst.so";
        }
    };

    template <class FST>
    class FstRegisterer : public GenericRegisterer<FstRegister<typename FST::Arc>> {
    public:
        using Arc = typename FST::Arc;
        using Entry = typename FstRegister<Arc>::Entry;
        using Reader = typename FstRegister<Arc>::Reader;

        FstRegisterer()
                : GenericRegisterer<FstRegister<typename FST::Arc>>(FST().Type(),
                                                                    BuildEntry()) {}

    private:
        static Entry BuildEntry() {
            FST *(*reader)(std::istream & strm, const FstReadOptions &opts) =
            &FST::Read;
            return Entry(reinterpret_cast<Reader>(reader),
                         &FstRegisterer<FST>::Convert);
        }

        static Fst<Arc> *Convert(const Fst<Arc> &fst) { return new FST(fst); }
    };

#define REGISTER_FST(FST, Arc) \
  static fst::FstRegisterer<FST<Arc>> FST##_##Arc##_registerer

    template <class Arc>
    Fst<Arc> *Convert(const Fst<Arc> &fst, const string &fst_type) {
        auto *reg = FstRegister<Arc>::GetRegister();
        const auto converter = reg->GetConverter(fst_type);
        if (!converter) {
            FSTERROR() << "Fst::Convert: Unknown FST type " << fst_type << " (arc type "
                       << Arc::Type() << ")";
            return nullptr;
        }
        return converter(fst);
    }

}

generic-register.h

#include <string>
namespace fst {

    template <class Arc>
    class Fst;

    struct FstReadOptions;
    template <class Arc>
    struct FstRegisterEntry {
        using Reader = Fst<Arc> *(*)(std::istream &istrm, const FstReadOptions &opts);
        using Converter = Fst<Arc> *(*)(const Fst<Arc> &fst);

        Reader reader;
        Converter converter;

        explicit FstRegisterEntry(Reader reader = nullptr,
                                  Converter converter = nullptr)
                : reader(reader), converter(converter) {}
    };

    template <class Arc>
    class FstRegister
            : public GenericRegister<string, FstRegisterEntry<Arc>, FstRegister<Arc>> {
    public:
        using Reader = typename FstRegisterEntry<Arc>::Reader;
        using Converter = typename FstRegisterEntry<Arc>::Converter;

        const Reader GetReader(const string &type) const {
            return this->GetEntry(type).reader;
        }

        const Converter GetConverter(const string &type) const {
            return this->GetEntry(type).converter;
        }

    protected:
        string ConvertKeyToSoFilename(const string &key) const override {
            string legal_type(key);
            ConvertToLegalCSymbol(&legal_type);
            return legal_type + "-fst.so";
        }
    };

    template <class FST>
    class FstRegisterer : public GenericRegisterer<FstRegister<typename FST::Arc>> {
    public:
        using Arc = typename FST::Arc;
        using Entry = typename FstRegister<Arc>::Entry;
        using Reader = typename FstRegister<Arc>::Reader;

        FstRegisterer()
                : GenericRegisterer<FstRegister<typename FST::Arc>>(FST().Type(),
                                                                    BuildEntry()) {}

    private:
        static Entry BuildEntry() {
            FST *(*reader)(std::istream & strm, const FstReadOptions &opts) =
            &FST::Read;
            return Entry(reinterpret_cast<Reader>(reader),
                         &FstRegisterer<FST>::Convert);
        }

        static Fst<Arc> *Convert(const Fst<Arc> &fst) { return new FST(fst); }
    };

#define REGISTER_FST(FST, Arc) \
  static fst::FstRegisterer<FST<Arc>> FST##_##Arc##_registerer

    template <class Arc>
    Fst<Arc> *Convert(const Fst<Arc> &fst, const string &fst_type) {
        auto *reg = FstRegister<Arc>::GetRegister();
        const auto converter = reg->GetConverter(fst_type);
        if (!converter) {
            FSTERROR() << "Fst::Convert: Unknown FST type " << fst_type << " (arc type "
                       << Arc::Type() << ")";
            return nullptr;
        }
        return converter(fst);
    }

}

例五 函数指针

#include <iostream>
#include <map>

typedef int (*mathfunc)(int,int);
typedef std::map<std::string, mathfunc> BrepMap;
BrepMap g_brew_map;

#define RegisterMathFunc(func) \
namespace { \
    class __Register_##func{ \
        public: \
            __Register_##func() { g_brew_map[#func] = &func;}};\
    __Register_##func g_register_##func;}

int add(int a, int b){
    return a+b;
}
RegisterMathFunc(add)

int sub(int a, int b){
    return a-b;
}
RegisterMathFunc(sub)

int mul(int a, int b){
    return a*b;
}
RegisterMathFunc(mul)


int main()
{
    std::cout<< "number of register functions: " << g_brew_map.size() << std::endl;
    std::string math_method = "add";
    std::cout << "23 + 12  = " << g_brew_map[math_method](23,12) << std::endl;
    return 1;
}

number of register functions: 3
23 + 12 = 35

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值