(预处理)
#define 标识符 字符串
其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等
宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用# undef命令。
宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。
带参宏定义(使用它要格外小心啊)
最好:定义时要注意每个参数要加括号,最外层也要加括号
1. 带参宏定义中,宏名和形参表之间不能有空格出现。(字符串中可以出现空格)
2. 在带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。而宏调用中的实参有具体的值。要用它们去代换形参
,因此必须作类型说明。这是与函数中的情况不同的。在函数中,形参和实参是两个不同的量,各有自己的作用域,调用时
要把实参值赋予形参,进行“值传递”。而在带参宏中,只是符号代换,不存在值传递的问题。
3. 在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。
#define SQ(y) (y)*(y)
sq=SQ(a+1);
sq=a+1*a+1;
这与函数的调用是不同的,函数调用时要把实参表达式的值求出来再赋予形参。而宏代换中对实参表达式不作计算直接地照原样代换。
4. 在宏定义中,字符串内的形参通常要用括号括起来以避免出错。在上例中的宏定义中(y)*(y)表达式的y都用括号括起来,因此结果是正确的。
宏定义也可用来定义多个语句,在宏调用时,把这些语句又代换到源程序内。看下面的例子。
【例9.11】
#define SSSV(s1,s2,s3,v) s1=l*w;s2=l*h;s3=w*h;v=w*l*h;
main(){
int l=3,w=4,h=5,sa,sb,sc,vv;
SSSV(sa,sb,sc,vv);
printf("sa=%d\nsb=%d\nsc=%d\nvv=%d\n",sa,sb,sc,vv);
}
#include<stdlib.h>
#include <assert.h>// 断言
//下面是数组堆栈的宏 函数依次是 判空 判满 压入 置顶 输出
//##起到连接文本的作用
#define generic_stack(stack_type,suffix,stack_size) \
static stack_type stack##suffix[stack_size]; \
static int top_element##suffix=-1; \
int is_empty##suffix() \
{ \
return top_element##suffix==-1; \
} \
int is_full##suffix() \
{ \
return top_element##suffix==stack_size-1; \
} \
void push##suffix(stack_type value) \
{ \
assert(!is_full##suffix()); \
top_element##suffix+=1; \
stack##suffix[top_element##suffix]=value; \
} \
void pop##suffix() \
{ \
assert(!is_empty##suffix()); \
top_element##suffix-=1; \
} \
stack_type top##suffix() \
{ \
assert(!is_empty##suffix()); \
return stack##suffix[top_element##suffix]; \
}
generic_stack(int,_int,10)//这里最好不要用分号
void main()
{
push_int(5);//输入5
push_int(10);
push_int(20);
while(!is_empty_int())
{
printf("%d\n",top_int());//输出
pop_int();
}
}
但是楼主一定要小心宏定义后面的\,这个符号后面必须马上回车,不能加任何一个字符,空格 tab都不行。
C语言不支持嵌套函数定义
#define 标识符 字符串
其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等
宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用# undef命令。
宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。
带参宏定义(使用它要格外小心啊)
最好:定义时要注意每个参数要加括号,最外层也要加括号
1. 带参宏定义中,宏名和形参表之间不能有空格出现。(字符串中可以出现空格)
2. 在带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。而宏调用中的实参有具体的值。要用它们去代换形参
,因此必须作类型说明。这是与函数中的情况不同的。在函数中,形参和实参是两个不同的量,各有自己的作用域,调用时
要把实参值赋予形参,进行“值传递”。而在带参宏中,只是符号代换,不存在值传递的问题。
3. 在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。
#define SQ(y) (y)*(y)
sq=SQ(a+1);
sq=a+1*a+1;
这与函数的调用是不同的,函数调用时要把实参表达式的值求出来再赋予形参。而宏代换中对实参表达式不作计算直接地照原样代换。
4. 在宏定义中,字符串内的形参通常要用括号括起来以避免出错。在上例中的宏定义中(y)*(y)表达式的y都用括号括起来,因此结果是正确的。
宏定义也可用来定义多个语句,在宏调用时,把这些语句又代换到源程序内。看下面的例子。
【例9.11】
#define SSSV(s1,s2,s3,v) s1=l*w;s2=l*h;s3=w*h;v=w*l*h;
main(){
int l=3,w=4,h=5,sa,sb,sc,vv;
SSSV(sa,sb,sc,vv);
printf("sa=%d\nsb=%d\nsc=%d\nvv=%d\n",sa,sb,sc,vv);
}
在宏调用时,把4个语句展开并用实参代替形参。使计算结果送入实参之中。
5
#include<stdio.h>
#define swap(x,y,t) (t=x,x=y,y=t)
void main(){
int x=3,y=9,t;
swap(x,y,t);
printf("%d\n%d\n",x,y);
}
#include <stdio.h>
#define dprint(expr) printf(#expr " 111\n")
#define lian(a,b) a ## b
///第一个是把expr变为字符串;;;第二个是把a和b连在一起
void move1();
void main()
{
dprint(9%%\\);和程序中的字符串转换一样
lian(move,1)();
}
void move1()
{
dprint(9/3);
}
6
#include<stdio.h>#include<stdlib.h>
#include <assert.h>// 断言
//下面是数组堆栈的宏 函数依次是 判空 判满 压入 置顶 输出
//##起到连接文本的作用
#define generic_stack(stack_type,suffix,stack_size) \
static stack_type stack##suffix[stack_size]; \
static int top_element##suffix=-1; \
int is_empty##suffix() \
{ \
return top_element##suffix==-1; \
} \
int is_full##suffix() \
{ \
return top_element##suffix==stack_size-1; \
} \
void push##suffix(stack_type value) \
{ \
assert(!is_full##suffix()); \
top_element##suffix+=1; \
stack##suffix[top_element##suffix]=value; \
} \
void pop##suffix() \
{ \
assert(!is_empty##suffix()); \
top_element##suffix-=1; \
} \
stack_type top##suffix() \
{ \
assert(!is_empty##suffix()); \
return stack##suffix[top_element##suffix]; \
}
generic_stack(int,_int,10)//这里最好不要用分号
void main()
{
push_int(5);//输入5
push_int(10);
push_int(20);
while(!is_empty_int())
{
printf("%d\n",top_int());//输出
pop_int();
}
}
但是楼主一定要小心宏定义后面的\,这个符号后面必须马上回车,不能加任何一个字符,空格 tab都不行。
C语言不支持嵌套函数定义