C macros and C++ macros

Summarize C and C++ macros.

In fact, the macros that everyone often use are actually macros in C, but C++ has continued, so let’s review them first.


#define : define a macro

#undef : cancel the macro


#include : include header files


#ifdef returns true if the macro is already defined

#ifndef true if the macro is not defined


#if if the condition is true, execute the following

#else and #if are mutually exclusive

#elif is equivalent to the else if we use

#endif ends the #if scope


#error If standard error is encountered, output an error


#program uses standard methods, sending special commands to the compiler


The commonly used C macros have been finished, but they are actually some nonsense, too easy. Then I don't care, let's talk more


ANSI C also defines many macros that we can use when programming.

__DATE__ current date

__TIME__ current time

__FILE__ the current filename

__LINE__ Current line number

__STDC__ is 1 when the compiler compiles to the ANSI standard

The format is better if you work it out yourself.

And C preprocessing also provides various operators

1. Macro continuation operator \

So here it is suggested that if a newline is used, it is best to add this symbol.

2. Tag paste operator##

This example is better to understand

#include<stdio.h> 

#define tokenpaster(n) printf ("token"#n " = %d", token##n) 

int main(void){int token34 =40;

    
   
   tokenpaster(34);return0;}
    
There must be some understanding here. How is the result?

token34 = 40

This example demonstrates that token##n is concatenated into token34, here we use the string constantization operator (#) and the token paste operator (##)

define() operator

The preprocessor  defined  operator is used in constant expressions to determine whether an identifier has been defined using #define. True (non-zero) if the specified identifier is already defined. If the specified identifier is undefined, the value is false (zero).

The usage of #define operation is not listed, remember that it is a simple replacement, and pay attention to the use of parentheses is ok.


C's macros are finished, let's talk about C++.


The variable parameter macro of C++ is quite detailed when someone said it on the Internet, so copy it directly for reference only:


In GNU C, macros can take a variable number of arguments, just like functions, eg:
#define pr_debug(fmt,arg...) \
printk(KERN_DEBUG fmt,##arg)
with variadic macros Passing variadic lists
You may be familiar with using variadic lists in functions, such as:
void printf(const char* format, …);
Until recently, variadic lists could only be used in real functions, not using in the macro.
The C99 compiler standard has finally changed that, allowing you to define variadic macros, so you can use macros with variable parameter lists. A variadic macro looks like this:
#define debug(…) printf(__VA_ARGS__)
The default number represents a variable parameter list. Use the reserved name __VA_ARGS__ to pass arguments to the macro. When the macro call is expanded, the actual arguments are passed to printf(). For example:
Debug("Y = %d\n", y);
and the processor would replace the macro call with:
printf("Y = %d\n", y);
because debug() is a variadic argument macro, you can pass a different number of arguments in each call:
debug("test"); //A
variadic macro is not officially supported by ANSI/ISO C++. Therefore, you should check your compiler to see if it supports this technology.
Use GCC and C99's variadic macros to print debugging information more easily.
The variadic macro definitions provided by gcc's preprocessing are really useful: 
#ifdef DEBUG
#define dbgprint(format,args...) \
fprintf(stderr, format, ##args)
#else
#define dbgprint(format,args...)
#endif
如此定义之后,代码中就可以用dbgprint了,例如dbgprint("aaa %s", __FILE__);。感觉这个功能比较Cool  :em11: 
下面是C99的方法: 
#define dgbmsg(fmt,...) \
printf(fmt,__VA_ARGS__)
新的C99规范支持了可变参数的宏
具体使用如下:
以下内容为程序代码:
#include <stdarg.h> #include <stdio.h>
#define LOGSTRINGS(fm, ...) printf(fm,__VA_ARGS__)
int main() {      LOGSTRINGS("hello, %d ", 10);      return 0; } 
但现在似乎只有gcc才支持。
可变参数的宏里的‘##’操作说明
带有可变参数的宏(Macros with a Variable Number of Arguments)
在1999年版本的ISO C 标准中,宏可以象函数一样,定义时可以带有可变参数。宏的语法和函数的语法类似。下面有个例子:
#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)
这里,‘…’指可变参数。这类宏在被调用时,它(这里指‘…’)被表示成零个或多个符号,包括里面的逗号,一直到到右括弧结束为止。当被调用时,在宏体(macro body)中,那些符号序列集合将代替里面的__VA_ARGS__标识符。更多的信息可以参考CPP手册。
GCC始终支持复杂的宏,它使用一种不同的语法从而可以使你可以给可变参数一个名字,如同其它参数一样。例如下面的例子:
#define debug(format, args...) fprintf (stderr, format, args)
这和上面举的那个ISO C定义的宏例子是完全一样的,但是这么写可读性更强并且更容易进行描述。
GNU CPP还有两种更复杂的宏扩展,支持上面两种格式的定义格式。
在标准C里,你不能省略可变参数,但是你却可以给它传递一个空的参数。例如,下面的宏调用在ISO C里是非法的,因为字符串后面没有逗号:
debug ("A message")
GNU CPP在这种情况下可以让你完全的忽略可变参数。在上面的例子中,编译器仍然会有问题(complain),因为宏展开后,里面的字符串后面会有个多余的逗号。
为了解决这个问题,CPP使用一个特殊的‘##’操作。书写格式为:
#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
这里,如果可变参数被忽略或为空,‘##’操作将使预处理器(preprocessor)去除掉它前面的那个逗号。如果你在宏调用时,确实提供了一些可变参数,GNU CPP也会工作正常,它会把这些可变参数放到逗号的后面。象其它的pasted macro参数一样,这些参数不是宏的扩展。
怎样写参数个数可变的宏
一种流行的技巧是用一个单独的用括弧括起来的的 ``参数" 定义和调用宏, 参数在 宏扩展的时候成为类似 printf() 那样的函数的整个参数列表。
#define DEBUG(args) (printf("DEBUG: "), printf args)
if(n != 0) DEBUG(("n is %d\n", n));
明显的缺陷是调用者必须记住使用一对额外的括弧。
gcc 有一个扩展可以让函数式的宏接受可变个数的参数。 但这不是标准。另一种 可能的解决方案是根据参数个数使用多个宏 (DEBUG1, DEBUG2, 等等), 或者用 逗号玩个这样的花招:
#define DEBUG(args) (printf("DEBUG: "), printf(args))
#define _ ,
DEBUG("i = %d" _ i);
C99 引入了对参数个数可变的函数式宏的正式支持。在宏 ``原型" 的末尾加上符号 ... (就像在参数可变的函数定义中), 宏定义中的伪宏 __VA_ARGS__ 就会在调用是 替换成可变参数。
最后, 你总是可以使用真实的函数, 接受明确定义的可变参数
如果你需要替换宏, 使用一个 函数和一个非函数式宏, 如 #define printf myprintf。


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325444653&siteId=291194637