1.宏定义
语法: #define 宏名字[(形参表)] 替换文本
其中,宏名字是一个标识符;
形参表为:(形参名1, 形参名2,...形参名n), 没有类型;
替换文本是一串字符.
宏调用和函数调用不同,是把程序中所有宏调用 "宏名字(实参表)", 用替换文本(实参代替形参)代替.
没有函数的跳转过程.
例如:
#define mul(x, y) ((x) * (y))
注意:此处必须加括号,否则,
(1)mul(x - 1, y + 1); 展开为 x - 1 * y + 1; //内层必须加()
(2)1 / mul(x, y); 展开为1 / x * y; //外层也必须加()
另外,替换时,实参尽可能不要有副作用.
例如:
#define max(x, y) ((x) > (y) ? (x) : (y))
max(x++, y) 展开为 ((x++) > (y) ? (x++) : (y))
2.文件包含
#include "文件名"
头文件(*.h)一般包含:
类型定义,宏定义,函数原型,外部变量定义.
调用其它文件中函数的代码,是在link的过程中由linker将*.obj文件进行link处理的.
3.条件编译
#if 条件1
代码1
#else 条件2
代码2
#endif
4.参数个数不确定的函数
形参表写法:(形参类型1 形参名1, ..., 形参类型n 形参名n, ... )
在程序中如何获取不确定的参数?
函数库提供了 stdarg.h, 一个类型, 2个宏.
typedef void * va_list; //va_list是一个指针类型
va_start(p, para); //para是最后一个确定参数的名字,这个宏给指针变量p赋初值,指向第一个不确定的参数
变量 = va_arg(p, 类型说明符);
//取出p所指的不定参数的值,类型说明符说明了这个值的类型,同时p自动的改指下一个可变参数.
示例程序代码如下:
#include "stdio.h"
#include "stdarg.h"
#include "stdlib.h"
void scanf_e(char *c, ...)
{
char a[1000], *p, *q;
va_list r;
va_start(r, c);
while(*c != '/0')
{
gets(a);
switch(*c)
{
case 'd':
*va_arg(r, int *) = atoi(a);
break;
case 'f':
*va_arg(r, double *) = atof(a);
break;
case 's':
p = va_arg(r, char *);
q = a;
while(*p++ = *q++);
}
c++;
}
}
void main()
{
int a;
double b;
char c[100];
scanf_e("dfs", &a, &b, c);
printf("%d/t%f/t%s", a, b, c);
}
<补充>
找了一下源代码, <stdarg.h>.
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
这里的宏 _INTSIZEOF(n) 挺有意思。
例如:
#include <stdio.h>
struct student
{
int id;
int sex;
int age;
char name[10];
};
struct student s1, s2;
#define size(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
int main()
{
printf("%d/n", &s1);
printf("%d/n", &s2);
printf( "%d/n", size(student));
return 0;
}
输出结果:
4373256
4373280
24
相差24个字节,而不是3 * 4 + 10 = 22个。
宏_INTSIZEOF(n) 达到此目的。
牛。