全局变量
- 定义在函数外部的变量是全局变量。
- 全局变量具有全局的生存期和作用域
- 全局变量与任何函数都无关
- 在任何函数内部都可以使用全局变量
- 不能使用变量给全局变量初始化
- 不初始化的全局变量默认为NULL
- 函数内的同名变量会隐藏全局变量
int a = 1;
{
int a = 2;
{
int a = 3;
printf("%d\n",a);
}
}
output: 3;
静态本地变量
-
使用static修饰一个变量变量使其变成静态本地变量
-
静态本地变量可以理解为特殊的全局变量(生存期相同,内存区域相同,作用域不同)
-
静态本地变量具有全局生存期,但作用域为局部作用域
- static的意思是局部作用域(本地可访问)
eg:
#include<stdio.h>
int f(void);
int main(){
f();
f();
return 0;
}
int f(void){
int var = 1;
static int static_var = 1;
var++;
static_var++;
printf("var => %d\nstatic_var => %d\n",var,static_var);
}
output:
var => 2
static_var => 2
var => 2
static_var => 3
返回指针的函数
-
返回函数内本地变量的指针是危险的,离开此函数后,谁也无法保证这片内存空间会不会分配给别人。
-
返回全局或者静态本地变量是安全的,他们和函数无关。
-
返回在函数内malloc的内存是安全的,但是容易出问题,不推荐。
-
返回传入函数的指针是安全的。
尽量避免使用全局变量
宏定义
#define
-
开头的是编译预处理指令
- 他们不是C语言的成分,但是C语言程序离不开他们
-
define用来定义一个宏
#define 标识符 值
// 注意,后面没有分号(他不是C语言的语句)
- 标识符必须是一个单词,值是什么都可以
写了define后,预编译所执行的操作是简单的“文本”替换。把代码中所有出现标识符的地方替换为后面的值,可以使用能够 gcc --save-temps
来查看预编译后产生的文件,来查看这件事。
宏
- 后面的宏中如果出现前面宏中定义的标识符,也会被替换
- 宏需要写在一行,如果需要多行书写,可以在行尾加
\
(不只是宏可以这样,C语言代码也可以) - 宏也可以写注释,不会被当作宏的一部分
- 没有值的宏可以用作条件编译,后面可以使用其他预处理质量来检测这个宏是否定义过。(如
#define _DEBUG
)
预定义的宏
这些宏默认提供的,可以实现一些功能
宏 | 用处 |
---|---|
__LINE__ | 当前行号 |
__FILE__ | 当前文件名 |
__DATE__ | 编译日期 |
__TIME__ | 编译时间 |
__FUNC__ | 当前所在的函数名 |
__STDC__ | __STDC__是预定义宏。当它被定义后,编译器将按照ansic标准来编译你的c程序。 |
多个源代码文件
在设计大程序时,不可能将所有的代码都写在 main.c
中,一般将一个程序拆分成多个 .c
文件.可以使用下面命令将多个 .c
文件编译成一个可执行程序:
gcc main.c [xxx.c yyy.c zzz.c] [-o] [output]
如果使用ide集成开发环境,一般会有项目,编译时会将项目中的 .c
文件编译成一个可执行程序.
头文件
头文件
我们将多个 .c
文件编译成一个可执行程序时.并不是将其他.c文件插入到 main.c 的某一个部位.所以 main.c
在使用其他 .c
文件中的函数时,需要在开头声明一下函数原型.
如果不声明函数原型,但是你对函数参数的传入和结果的传出使用正确的话,也不会出现问题.但是一旦使用错误,就会出现问题.
此时就需要用到头文件了,头文件的后缀为 .h
.我们可以使用 #include
来插入一个头文件.
#include <stdlib.h>
#include "node.h"
<>
引入头文件,会在系统特定的目录找这个头文件.一般用于引入标准库的头文件.""
引入头文件,会先在当前目录寻找这个头文件,找不到时再去系统特定目录寻找,一般用于引入自己写的头文件.
头文件中一般包含了这些函数的函数原型(并不包含函数本身,如果你想也可以,但一般不这么做).在编译预处理时,编译器会把头文件插入在引入头文件的位置.这样就不用在 main.c
中声明函数原型了.
关于#include的一个误区
-
#include
不是用来引入函数库的 -
stdio.h
里只有printf
的函数原型,printf
的函数写在别的地方 -
C语言编译器会默认引入所有的标准库
-
#include<stdio.h>
只是为了让编译器知道printf
的函数原型,确保在调用时给出的参数值是正确的类型
在学这节之前,我也一直认为 #include
是引入一个函数库o(╥﹏╥)o
局部函数
如果希望一个 .c
文件中的某一个函数,只能在该 .c
中使用. 需要在函数定义的开头加 static
来修饰. 此时这个函数可以看做一个局部函数,只在他所在的 .c
文件中生效.
声明
声明有很多种, 可以使用 extern
来声明一个变量.
int i; // 变量的定义
extern int i; // 变量的声明
这个关系有点像函数的定义和函数原型的声明. 同样,如果想在 main.c
中使用一个其他 .c
文件的全局变量,就需要声明一下.
-
声明不会产生代码.
-
定义会产生代码.
头文件
- 只有声明可以写在头文件中.这是一个约定俗成的规矩,并不强制.
- 如果在头文件中写定义,可能会导致同一实体被重复定义.或者出现同名的定义.
- 某些编译器允许多个编译单元中有同名函数的存在,或者用
weak
修饰符强调这种存在.
- 某些编译器允许多个编译单元中有同名函数的存在,或者用
重复声明
- 同一个编译单元中,同名的结构不能被重复声明.
- 如果头文件中声明了一个结构,这个结构很可能会被重复声明导致程序出错.
- 我们可以用 "标准头文件结构" 来避免这种情况发生.
标准头文件结构:
/*
如果这个头文件被引用过一次,___XXX___就会被定义,下一次重复引用时,直接跳到#endif,中间的代码就不会被引用了.
*/
#ifndef __XXX__ // 如果没有定义__XXX___
#define __XXX__ // 定义___XXX___
..CODE..
#endif
这样就可以保证一个头文件只会被引用一次..
标签:__,头文件,函数,int,笔记,C语言,var,全局变量 From: https://www.cnblogs.com/orzmiku/p/17644191.html