首先介绍以下几个关键字
register
作用是建议编译器将变量存储在寄存器中,以加快访问速度,需要注意的是它定义的变量不能取地址,因为寄存器变量无内存地址,如以下代码建议编译器将i放入寄存器
#include <stdio.h>
int a = 0;
void test(void)
{
//static int b = a++;
static int b = 0;
b = a++;
printf("a = %d b = %d\n",a,b);
}
int main(void)
{
register int i = 0;
printf("&i = %p\n",&i);
for (i = 0; i < 100; ++i)
{
test();
}
return 0;
}
extern
它的作用是声明变量在其它文件中定义,或者是用于多文件共享全局变量或函数
Static
它的主要作用是限制作用域或生命周期,具体用法分为两种情况:
一种是定义静态局部变量,他的生命周期为整个程序的运行期间,作用域仅限于函数以内
另一种是定义全局变量,使变量只能作用在文件内部
C语言从程序编写到执行输出的过程中有着以下几个阶段:
预处理-->源程序-->编译-->汇编-->a.out
而预处理与C语言的关系首先是他一般放在程序的开头,包括了宏定义,文件包含,条件编译
宏定义
语法结构:
#define 标识符 字符串
define:也就是预处理命令
标识符:宏名
字符串:宏值(这个字符串只是预处理阶段的文本信息,与C语言中的字符串是两个概念)
所以结构也可看作:
#define 宏名 宏值
eg:
#define N 10
它的主要用途可分为以下几点:
1.用一个更有可读性的标识符(宏名)代表一个具体的值(常量)提高代码的可读性
2.符号常量,起到见名知意的效果,宏定义代码修改则程序中用到的宏定义参量都会改
需要注意的是:a.宏定义的末尾不能写分号 b.宏名--一般建议大写,由此区别于变量名
c.宏名是区分大小写的 d.从定义处开始,到后面文件结束
3.预处理的本质是“文本的原样替换”
比如以下代码:
#include<stdio.h>
#define ARRAY_SIZE 10
int main()
{
int a[ARRAY_SIZE]={0};
printf("%d",ARRAY_SIZE);
}
ARRAY_SIZE是一个宏名,10是它的宏值,它在代码中的作用就是将数组长度赋值进去
带参宏
带参宏的语法结构是这样的:
#define 宏名(参数) 宏值
eg:
相乘
#define MUL(a,b) a*b
MUL(1,2) //使用
需要注意的的是:1.宏函数并不是函数,只是预处理时的宏定义,带参宏的使用本质同样也是文本的原样替换,是没有类型检查的
2.宏定义做的是文本的原样替换导致有些时候替换结果不符合预期,因此应该在能加()的地方都加(),即变量处;
3.宏的嵌套的本质就也是逐层替换
4.宏定义的结束标志就是换行,续行符:\后面不能有任何其他的符号
#include<stdio.h>
#define PI 3.1415
#define FINDL(r) 2*PI*(r)
#define FINDS(r) PI*(r)*(r)
int main()
{
int r;
scanf("%d",&r);
printf("周长为 %.4f\n,面积为%.4f\n",FINDL(r),FINDS(r));
}
如上所示代码,定义的两个宏函数的宏值都是表达式,可直接在main函数中调用并赋值
文件包含
主要有以下两种格式:
#include <文件名>
#include "文件名"
他们的作用都是在预处理阶段,用文件中的内容替换include命令
区别是:
<>:表示在系统默认的路径下寻找包含的文件,一般是系统默认的头文件
"": 表示在现在当前位置下寻找,如果没有找到再到系统的默认路径下寻找,一般是自己写的头文件
条件编译
#ifdef 标识符
程序段1
#else
程序段2
#endif
说明:如果标识符已定义则将程序段1包含到最终的文件中,否则则将程序段2包含到最终的文件中
#ifndef 标识符
程序段1
#else
程序段2
#endif
说明:如果 标识符未定义则将程序段1 包含到最终的文件中否则则将程序段2 包含到最终的文件中
#if 表达式
程序段1
#else
程序段2
#endif
说明:如果表达式为真,则将程序段1包含到最终的文件中,否则则将程序段2包含到最终的文件中