我们先来回顾一下全局变量,
下面这个代码只是为了验证全局变量可以被每一个函数调用
#include<stdio.h>
int f(void);
int gAll = 12;
int main()
{
printf("in %s gAll = %d\n",__func__,gAll);//__func__这是C语言预定义的宏,表示的就是它所在的函数
f();
printf("agn in %s gAll = %d\n",__func__,gAll);
return 0;
}
int f(void)
{
printf("in %s gAll = %d\n",__func__,gAll);
gAll+=2;
printf("agn in %s gAll = %d\n",__func__,gAll);
return gAll;
}
这里需要做一些补充
1. 没有做初始化的全局变量会得到0值
指针会得到NULL值
2. 只能用编译时刻已知的值里初始化全局变量
比如上面的gAll
我们可以给它赋值 12 或任何的数字
但是我们不能这样 int gAll = f();
也不能这样 int gAll = 12;
int g2 = gAll;
不过我们可以这样 const int aAll=12;
int g2 = gAll;
3. 他们的初始化发生在main函数之前
之前的笔记里面有 static 关键字
它的作用是将本地变量变为静态本地变量
而实际上,静态本地变量是特殊的全局变量
它们位于相同的内存区域,
静态本地变量具有全局变量的生存期,函数内的局部作用域
编译预处理指令
C语言中 # 开头的是编译预处理指令,当然不止C语言使用
它不是C语言的成分,但是C语言程序离不开它
#define 用来定义一个宏
#include<stdio.h>
const double PI = 3.14159;
int main()
{
printf("%f\n",2*PI*3.0);
return 0;
}
c99 中我们可以这样做,用 const
c99之前是怎么解决的?
#define PI 3.14159
PI是这个宏的名字, 3.14159 是这个宏的值
这是编译预处理指令,编译前编译器会将所有的 PI 换成 3.14159
#define <名字> <值>
注意结尾没有分号,这不是一条C语言的语句
名字必须是一个单词,值可以是任何东西
在C语言的编译器开始编译之前,会将程序中的名字换成值
如果一个宏的值中还有其他宏的名字,也会被替换
如果一个宏的值超过一行,行末需要加\
宏里面也可以有注释
预定义的宏
__LINE__ 表示所在行的行号
__FILE__ 表示源文件的文件名
__DATE__ 编译时刻的日期
__TIME__ 编译时刻的时间
__STDC__
还可以定义像函数的宏
#define cube(x) ((x)*(x)*(x))
宏可以带参数
x就是这个参数,将来是会被替换的
带参数的宏的原则
一切都要带括号
整个宏的值要带括号
每一个参数都要带括号
这样能保证我们的代码不会出错
宏定义可以嵌套,也可以有多个参数
#define min(a,b) a>b?a:b
min = a>b?a:b 这是条件运算符作用类似于 if else
if(a>b){
max=b;
}else
max=a;
在大型程序的代码中,宏使用的非常普遍
可以非常复杂,如生产函数
部分的宏也会被 inline 函数取代
其它编译预处理指令
error 条件编译
工程建立
为什么需要工程?
当我们的 .c 文件很大,有很多个函数的时候,
我们可以将它分为多个 .c 文件,
当然这两个文件要太同一个工程下面,我们编译运行它,同样是可以的
编译器会将这两个文件链接起来
头文件
我们可以把函数声明放在 .h 文件下,使用时 #include就可以直接使用这个函数
插入的头文件可以有两种引用方式
""和<>两种
那么如何选择呢
""要求编译器首先在当前目录下寻找这个文件,
如果没有再到编译器指定的目录去找
<>让编译器只在指定目录去找
当然编译器知道自己的标准库的头文件在哪
环境变量和编译器命令行参数也可以指定寻找头文件的目录
#include<stdio.h>
#include"max.h"
int main()
{
int a=6;
int b=12;
printf("%d",max(a,b));
return 0;
}
int max(int a,int b){
if(a>b){
b=a;
}
return b;
}
我在当前目录下写了一个max.h文件,上面就可以省略申明
#include
1.#include 不是用来引入库的
2. stdio.h等头文件里面只有函数的声明,而函数的库在其他地方,
在某个 .lib文件里面
3. 现在的编译器默认会引入所有的标准库
我们在使用和定义这个函数的时候都应该 #include 这个头文件
一般的做法就是任何.c文件都有对应同名的.h文件,
把所有对外公开的函数原型和全局变量的声明都放进去
全局变量是可以让所有.c文件使用的,
如果在全局变量加上static关键字,就只能在这个.c文件内使用
变量的声明
int i ;这个是变量的定义,如果我们要发到头文件内,是需要声明的
extern int i;这个就是变量声明
声明和定义
声明是不产生代码的东西
函数原型,变量声明,结构声明,宏声明,枚举声明,类型声明,inline函数
定义是产生代码的东西
函数,全局变量//就这两种
一个.c文件中只能有声明,并且不能重复声明,但是程序结构复杂的时候又很难避免重复
所以
我们一般在头文件中加上这几句//标准头文件结构
#ifndef _MAX_H_ //如果没有定义这个宏,执行下面的指令
#define _MAX_H_ //定义宏
...
...
#endif // _MAX_H_//结束上面的if
# 空指令,无任何效果
#include 包含一个源代码文件
#define 定义宏
#undef 取消已定义的宏
#if 如果给定条件为真,执行下面指令与程序
#ifdef 如果宏已经定义,执行下面指令与程序
#ifndef 如果宏没有定义,执行下面指令与程序
#elif 如果前面的#if给定条件不为真,当前条件为真,执行下面指令与程序
#endif 结束一个#if……#else条件编译块
#error 停止编译并显示错误信息
这些都是预处理指令
宏定义时可能出现##,它的意思是链接前后数据
例如:
#define conn(str) str##myname
conn(123);
这句的意思就是等价于123myname
|