vlambda博客
学习文章列表

c语言----变量和预处理

c语言----变量和预处理

c语言----变量和预处理    全局变量    全局变量初始化    静态本地变量    *返回指针的函数    小贴士    编译预处理指令    宏        #define        没有值的宏        预定义宏        带参数的宏        带参数宏的原则    #include后面到底使用“”还是<>?声明

全局变量

  1. 定义在函数外边的变量是全局变量
  2. 全局变量具有全局的生存期和作用域
  3. 他们和任何函数都无关
  4. 在任何函数都可以使用它

全局变量初始化

  1. 没有做初始化的全局变量会得到0值
  2. 指针会得到NULL
  3. 只能用编译时刻已知的值来初始化全局变量
  4. 它们的初始化在main主函数发生前完成

如果函数内部存在与全局变量同名的变量,则全局变量会被隐藏(优先使用局部变量)

静态本地变量

  1. 在本地变量定义时加上 static修饰符就会变成静态本地变量
  2. 当函数离开的时候,静态本地变量会继续存在并保持其值
  3. 静态本地变量的初始化只会在第一次进入这个函数时做,,以后进入这个函数会保持上次离开的值
#include"stdio.h" 
int f();
int i=0;
void main()
{
for(i=0;i<10;i++)
f();
}
int f()
{
static int a=0;
printf("%d次调用a的值%d\n",i,a);
a+=2;
return a;
}

结果:


如果a不是静态变量(static int a=0变为int a)

结果:

c语言----变量和预处理


实际上静态本地变量就是特殊的全局变量。但是作用域只能在定义它的函数内部

*返回指针的函数

  1. 返回本地变量是危险的。因为一旦子函数完成运算,其里面的本地变量的地址空间会被收回,然后分配给后续函数使用
  2. 返回全局变量或者静态本地变量的地址是安全的
  3. 返回在函数内的malloc的内存是安全的,但容易造成问题
  4. 最好的做法是返回传入的指针

## 小贴士

  1. 不要使用全局变量在函数间传递参数和结果
  2. 尽量避免使用全局变量

编译预处理指令

  1. #开头的就是编译预处理指令
  2. 他们不是c语言的成分,但是c语言程序离不开他们

#define

  1. 用法: #define <名字> <值>
  2. 注意:没有结尾的分号,因为不是c语句
  3. 名字必须是一个单词,值可以是各种东西
  4. c语言在编译器编译之前,编译预处理程序会打程序中的名字全部换为值

什么叫做宏呢?

按照上面定义出来的东西叫做宏

  1. 如果一个宏的值中有其他宏的名字,也是会被替换的
  2. 如果一个宏的值超过一行,最后一行之前的行末尾加\
  3. 宏的值后面出现的注释不会当成宏的一部分
#include"stdio.h" 
#define PI 3.141596
#define PI_1 2*PI //宏中带宏
#define PRT printf("PI=%f\n",PI);\ //定义多行宏
printf("2*PI=%f\n",PI_1);
void main()
{
PRT
}

结果:


没有值的宏

#define _DEBUG

这类宏是用来条件编译的,后面的其他预处理指令来检查这个宏是否已经被定义了

预定义宏

描 述
DATE 源文件的编泽口期,用 “Mmm dd yyy”形式的字符串常量表示
FILE 当前源文件的名称,用字符串常量表示
LINE 当前源文件中的行号,用十进制整数常量表示,它可以随#line指令改变
TIME 当前源文件的最新编译吋间,用“hh:mm:ss”形式的宁符串常量表示
STDC 如果今前编泽器符合ISO标准,那么该宏的值为1,否则未定义

带参数的宏

#include"stdio.h" 
#define cube(x) (x)*(x)*(x)//括号尽量不要少
void main()
{
printf("%d\n",cube(5+5)); //宏定义中的x用5+5代替
}

带参数宏的原则

一切要有括号:整个值要有括号,参数出现的每一个地方都要括号

#define cube(x) ((x)*3.14*3.14) //正确使用

#define cube(x) (x)*3.14*3.14 //错误使用
#define cube(x) (x*3.14*3.14) //错误使用

可以带有多个参数,也可以嵌套使用

#define min(a,b) ((a)>(b)?(a):(b))

注意:使用宏不能加分号,因为我们一般在定义宏时就加了分号

  1. 在大型程序的代码中使用普遍
  2. 可以非常复杂,如“产生”函数
  3. 部分宏会被 inline 函数代替

#include后面到底使用“”还是<>?

""要求编译器首先在当前目录(.c所在的目录)找寻这个文件,如果没有就在编译器指定的目录去找

<>让编译器只在指定目录下找

编译器自己知道自己的标准库的头文件在哪里

一般的做法就是任何.c都有和它同名的.h,把所有的对外公开的函数原型和全局变量的声明都放进去

声明

怎么声明一个全局变量,使其在各个.c文件被使用?

extern int a//声明一个全局变量(不能初始化)

int a//定义一个变量

怎么保证.h文件只被编译一次?

我们知道所有变量只能被编译一次的。当变量被定义在.h中,当多次调用这个.h文件。在编译时会多次编译

//标准头文件结构
#ifndef _MAX_H_ //如果没有定义_MAX_这个宏的话,就定义这个宏,如果存在直接跳到endif
#define _MAX_H_


#endif