C语言笔记_me
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
预编译处理:
1.宏定义
形式:#define 标识符字符串
说明:
宏名一般用大写。
宏定义不作语法检查,只有在编译被宏展开后的源程序时才会报错。
宏定义不是C语句,不在行末加分号。
宏名有效范围为定义到本源文件结束。
可以用#undef命令终止定义的作用域。
在宏定义时,可以引用已定义的宏名
带参数的宏定义
形式:#define 宏名(参数表)字符串
2.文件包含处理
#include “文件1”
就是交文件1的全部内容复制插入到# include位置,作为一个源文件进行编译。
3.条件编译
条件编译:指不对整个程序都编译,而是编译满足条件的那部分。有以下几种形式:
①.# ifdef 标识符
程序段1
#else
程序段2
#endif
作用:当标识符在前面已经被定义过(一般用#define),则对程序段1编译,否则
对程序段2编译。
②.# if 标识符
程序段1
#else
程序段2
#endif
作用:和# ifdef相反,当标识符没被定义过时,才对程序段1编译。
③.# ifndef 表达式
程序段1
#else
程序段2
#endif
作用:当表达式值为真(非0)时,对程序段1编译,否则对程序段2编译。
条件编译的应用
全局变量应该是得到内存分配且可以被其他模块通过C语言中extern关键字调用的变量。因此,必须在.C 和.H 文件中定义。这种重复的定义很容易导致错误。
以下讨论只需用在一个头文件中定义一次,
1.首先,说明一个条件编译命令:
#ifdef 标识符
程序1
#else
程序2
#endif
先在一个头文件(.h)中输入条件编译命令。
那么,对C程序(.c)进行编译时,若程序包令:
#include标识符
或#include标识符0
即:只要有标识符出现,编译时就会加入程序1,一并进入编译。否则,加入程序2。
例:在uCOS_II.H 中包含:
#ifdef OS_GLOBALS
#define OS_EXT
#else
#define OS_EXT extern
#endif
OS_EXT INT32U OSIdleCtr;
OS_EXT INT32U OSIdleCtrRun;
OS_EXT INT32U OSIdleCtrMax;
同时,uCOS_II.C中包含:
#define OS_GLOBALS
(当然,所有.C应该都包含#include uCOS_II.H,这样才达到.C文件能访问全局
变量)
这样,当编译器处理uCOS_II.C时,它使得头文件变成如下所示,因为OS_EXT被设置为空。编译器就全局变量分配在内存,而当编译其他不含#define OS_GLOBALS的.C文件时,OS_EXT被设置为extern,表示该变量为外部定义的全局变量,不用再分配内存了。
其实,这样是将一个C文件的所有全局变量定义在一个头文件中,而所有C文件都包含这个头文件,这样防止重复定义一个全局变量而发生错误。
其实,条件编译命令还有一种形式:
#if 标识符
程序1
#else
程序2
#endif
这种方式有些不同,只有当标识符为真时,才执行程序1,否则执行程序2。
使用static定义的问题
一个static的变量,其实就是全局变量,只不过它是有作用域,它可用于保存变量所在函数被累次调用期间的中间状态,比如:
int nCount()
{
static int cout=0;
……
count++;
……
}
cout变量的值会跟随着函数的调用次而递增,函数退出后,cout的值还存在,只是cout 只能在函数中才能被访问(函数作用域)。而cout的内存也只会在函数第一次被调用时才会被分配和初始化,以后每次进入函数,都不为static分配了,而直接使用上一次的值。
注:如果在模块内(但在函数体外)声明一个静态变量,则模块内所有的函数都可访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
如果在模块内,用static声明一个函数,则这个函数只可被这一模块内的其它函数调用。也就是,这个函数被限制在声明它的模块的本地范围内使用。
数据类型
1.指针:
指针:地址。
指针变量:就是用来存放指针(地址)的变量。
变量的指针(变量的地址)和指向变量的指针变量(用来存放变量的地址的变量)
“指针”可以理解为“地址”,而“指向”可以理解为“存放**的地址”
例:
int a; //定义一个整型数
int *a; //定义一个指向整型数的指针
int **a; //定义一个指向指针的指针,它指向的指针是指向一个整型数
int a[10]; //定义一个有10个整型数的数组
int *a[10]; //定义一个有10个指针的数组,该指针指向一个整型数
int (*a)(int); //一个指向函数的指针,该函数有一个整型参数并返回一个整型数
int (*a[10])(int); //一个有10个指针的数组,该指针指向一个函数, 该函数有一个整型参数并返回一个整型
例:要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。
解:int *ptr;
ptr = (int*)0x67a9
*ptr = 0xaa55;
①.指向函数的指针变量
一个函数在编译时被分配一个入口地址,这个入口地址就称为函数的指针。
函数名代表函数的入口地址。
例:Int max(int x,int y);
函数的调用方法:
常用方法“
Int c;
c = max(a,b);
通过指针来调用:
Int (*p)(); //定义一个指向函数的指针变量
p=max; //函数的入口地址赋给函数指针变量p
c=(*p)(a,b);
返回指针值的函数:
定义形式:类型标识符*函数名(参数表)
例:int *a(x,y)//返回一个指向整型的指针
注:在调用时,要先定义一个适当的指针来接收函数的返回值。
注意:int *func(void)和int (*func)(void)的区别
int *func(void);//这是返回一个整型指针的函数
int (*func)(void); //这是一个函数指针
②.函数指针数组(应用)
例:在一计算器的中有如下一些语句:
Switch(oper){
Case ADD:
Result = add(op1,op2);break;