1、全局变量和局部变量的基本概念
局部变量
概念 : 局部变量 就是定义在函数,代码块和函数星灿烈表中的变量,我们就称之为局部变量。
作用范围 : 从定义的那一行开始 一直到 遇到大括号借宿 或者return为止
特点 :
相同作用域 范围不能出现同名的局部变量
不同作用域范围内 出现同名的局部变量,内部的局部变量 会覆盖外部的局部变量
注意 :
局部变量没有固定的初始化值,如果没有对局部变量进行初始化,那么局部变量中是一些随机的值,
特点 :
相同作用域 范围不能出现同名的局部变量
不同作用域范围内 出现同名的局部变量,内部的局部变量 会覆盖外部的局部变量
注意 :
局部变量没有固定的初始化值,如果没有对局部变量进行初始化,那么局部变量中是一些随机的值,
所以在开发中,千万不要使用未初始化的局部变量
存储位置:
局部变量 存储在栈中, 当作用域结束 系统会自动释放 栈中的局部变量
全局变量
存储位置:
局部变量 存储在栈中, 当作用域结束 系统会自动释放 栈中的局部变量
全局变量
概念 : 写在函数,代码块,形参列表外的变量,我们称之为全局变量
作用范围 : 从定义的那一行 开始 一直 遇到大括号结束(暂时这样认为)
特点 :
全局变量 和局部变量 可以同名
如果存在 和全局变量同名的局部变量,那么局部变量会覆盖全局变量
注意 :
全局变量如果没有进行初始化,那么系统默认会将全局变量初始化为0
存储位置 :
全局变量 存储在 静态区中, 他会随着程序的启动而创建,随着程序的结束而结束。
2、内部全局变量和外部全局变量
全局变量分两种:
1.外部局部变量,默认情况下 所有的全局变量都是外部全局变量
什么是外部全局变量? 可以被其他文件访问的全局变量 我们称之为外部全局变量
2.内部全局变量, 只要给全局变量加上 static 关键字 就是内部全局变量
什么是内部全局变量? 只能被当前文件 访问的全局变量 我们称之为全局变量
外部全局变量 有一个特点:
可以定义同名的外部全局变量
多个同名的外部全局变量 指向同一块存储空间
内部全局变量有一个特点:
也可以定义多个的内部全局变量
多个同名的全局变量 如果不在 同一个文件中,那么指向不同的存储空间
为了提高数据的安全性, 不让别人在其他文件修改我们的全局变量, C语言提供了另外一个用于修改全局变量的关键字, static
只要 用 static修饰的全局变量 就是内部全局变量, 只能在单钱文件中使用
这样就可以提高我们全局变量的安全性
如果多个文件存在同名的内部全局变量,相互不会影响
如果既有外部全局变量 也有内部全局变量,那么会优先访问 内部全局变量
extern
用于声明一个外部全局变量
声明只需要 在使用之前 声明就可以了
static
用于定义一个内部全局变量
声明 和定义的区别:
声明不会开辟存储空间
定义会开辟存储空间
1.外部局部变量,默认情况下 所有的全局变量都是外部全局变量
什么是外部全局变量? 可以被其他文件访问的全局变量 我们称之为外部全局变量
2.内部全局变量, 只要给全局变量加上 static 关键字 就是内部全局变量
什么是内部全局变量? 只能被当前文件 访问的全局变量 我们称之为全局变量
外部全局变量 有一个特点:
可以定义同名的外部全局变量
多个同名的外部全局变量 指向同一块存储空间
内部全局变量有一个特点:
也可以定义多个的内部全局变量
多个同名的全局变量 如果不在 同一个文件中,那么指向不同的存储空间
为了提高数据的安全性, 不让别人在其他文件修改我们的全局变量, C语言提供了另外一个用于修改全局变量的关键字, static
只要 用 static修饰的全局变量 就是内部全局变量, 只能在单钱文件中使用
这样就可以提高我们全局变量的安全性
如果多个文件存在同名的内部全局变量,相互不会影响
如果既有外部全局变量 也有内部全局变量,那么会优先访问 内部全局变量
extern
用于声明一个外部全局变量
声明只需要 在使用之前 声明就可以了
static
用于定义一个内部全局变量
声明 和定义的区别:
声明不会开辟存储空间
定义会开辟存储空间
3、static对局部变量的作用
应用场景 :
当某个方法的调用频率非常高,而该方法中有些变量的值 是固定不变的
那么这个时候 就可以使用 static来修饰该变量,让该变量 只开辟一次存储空间
这样可以提高程序的效率 和 性能。
当某个方法的调用频率非常高,而该方法中有些变量的值 是固定不变的
那么这个时候 就可以使用 static来修饰该变量,让该变量 只开辟一次存储空间
这样可以提高程序的效率 和 性能。
4、static和extern对函数-作用
函数 也分为 内部函数 和 外部函数。默认情况下所有的函数 都是外部函数
什么是外部函数 ?
什么是外部函数 ?
可以被其他文件 访问的函数 称之为 外部函数
什么是内部函数 ?
什么是内部函数 ?
只能在当前文件中访问的函数 称之为 内部函数
只要在函数的返回值前面加上一个 extren 就可以让函数变为一个外部函数, 由于默认就是外部函数, 所以在开发中 一般entern没人写
如果 extern 写在函数的实现中, 代表定义一个外部函数
如果 extern 写在函数的声明中, 代表声明一个外部函数
只要在函数的返回值 前面 加上 static就可以让函数 变为内部函数,其他文件就不能访问了
如果static写在函数的实现中, 代表定义一个内部函数
如果static写在函数的声明中, 代表声明一个内部函数
只要在函数的返回值前面加上一个 extren 就可以让函数变为一个外部函数, 由于默认就是外部函数, 所以在开发中 一般entern没人写
如果 extern 写在函数的实现中, 代表定义一个外部函数
如果 extern 写在函数的声明中, 代表声明一个外部函数
只要在函数的返回值 前面 加上 static就可以让函数 变为内部函数,其他文件就不能访问了
如果static写在函数的实现中, 代表定义一个内部函数
如果static写在函数的声明中, 代表声明一个内部函数
5、不带参数宏定义
预处理指令
什么是预处理指令:
在我们的文件 翻译成0和1 之前做的操作 我们称之为预处理指令
一般情况预处理指令 都是以 #号开头的
宏定义:
宏定义的格式
1.不带参数的宏定义
2.带参数的宏定义
#define 宏名 值
注意 : 宏定义后面不要写分号
宏定义的作用:
会在程序编译成0 和 1之前, 将所有宏名 替换成 宏的值
宏定义在什么时候替换
源代码 -> 预处理 -> 汇编 -> 二进制 -> 可执行程序
规范
一般情况宏名都大写,多个单词之间用_隔开, 并且每个单词全部大写
有的公司要求宏名 以k开头, 多个单吃之间用驼峰命名
#define kClassCount 10
宏定义也有作用域
从定义的哪一行开始, 一直到文件末尾
虽然默认情况下 宏定义的作用域 是从定义的哪一行开始, 一直到文件末尾, 但是我们也可以通过 对应的关键字 提前结束宏定义的作用域
#undef COUNT 提前结束宏定义
什么是预处理指令:
在我们的文件 翻译成0和1 之前做的操作 我们称之为预处理指令
一般情况预处理指令 都是以 #号开头的
宏定义:
宏定义的格式
1.不带参数的宏定义
2.带参数的宏定义
#define 宏名 值
注意 : 宏定义后面不要写分号
宏定义的作用:
会在程序编译成0 和 1之前, 将所有宏名 替换成 宏的值
宏定义在什么时候替换
源代码 -> 预处理 -> 汇编 -> 二进制 -> 可执行程序
规范
一般情况宏名都大写,多个单词之间用_隔开, 并且每个单词全部大写
有的公司要求宏名 以k开头, 多个单吃之间用驼峰命名
#define kClassCount 10
宏定义也有作用域
从定义的哪一行开始, 一直到文件末尾
虽然默认情况下 宏定义的作用域 是从定义的哪一行开始, 一直到文件末尾, 但是我们也可以通过 对应的关键字 提前结束宏定义的作用域
#undef COUNT 提前结束宏定义
6、带参数的宏定义
#define SUM(v1,v2) v1+v2
#define 代表要定义宏
SUM 宏的名称
(v1,v2) 参数, 注意点, 不需要写数据类型
v1+v2 用于替换的内容
宏定义 并不会做任何运算, 无论是有参数 还是没有参数 都仅仅是在翻译 0 和 1之前做一个简单的"替换"
SUM(v1,v2) 宏
v1+v2 值
什么时候 用带参数的宏定义 什么时候 用函数
如果函数内部的功能比较简单, 仅仅做一些简单的运算 那么可以使用宏定义, 使用宏定义效率更好,运算速度更快,
如果函数内部的功能比较复杂, 不仅仅是一些简单的运算, 那么建议使用函数
带参数的宏定义注意点
1.一般情况下 建议写带参数的宏的时候,给每个参数加上()
2.一般情况下 建议写带参数的宏的时候, 给结果也加上一个()
#define 代表要定义宏
SUM 宏的名称
(v1,v2) 参数, 注意点, 不需要写数据类型
v1+v2 用于替换的内容
宏定义 并不会做任何运算, 无论是有参数 还是没有参数 都仅仅是在翻译 0 和 1之前做一个简单的"替换"
SUM(v1,v2) 宏
v1+v2 值
什么时候 用带参数的宏定义 什么时候 用函数
如果函数内部的功能比较简单, 仅仅做一些简单的运算 那么可以使用宏定义, 使用宏定义效率更好,运算速度更快,
如果函数内部的功能比较复杂, 不仅仅是一些简单的运算, 那么建议使用函数
带参数的宏定义注意点
1.一般情况下 建议写带参数的宏的时候,给每个参数加上()
2.一般情况下 建议写带参数的宏的时候, 给结果也加上一个()
7、typedef
什么是 typedef ,他有什么作用
typedef 可以给一个已知的数据类型 起一个别名(外号)
利用typedef 给数据类型 起别名格式:
typedef 原有的数据类型 别名(外号);
注意 :
1.teyedef 不仅仅能给系统原有的数据类型 起别名, 也可以给一个自定义的数据类型起别名
2.利用teyedef 给数据类型起别名, 并不会生成一个新的数据类型, 仅仅是给原有的类型 起了一个别名而已
typedef 可以给一个已知的数据类型 起一个别名(外号)
利用typedef 给数据类型 起别名格式:
typedef 原有的数据类型 别名(外号);
注意 :
1.teyedef 不仅仅能给系统原有的数据类型 起别名, 也可以给一个自定义的数据类型起别名
2.利用teyedef 给数据类型起别名, 并不会生成一个新的数据类型, 仅仅是给原有的类型 起了一个别名而已
8、typedef和宏定义的区别
typedef int myInt;#define Inter int
// 一般情况下 如果要给数据类型 起一个名词 建议用typedef, 不要define
typedef char * String;
// 宏定义仅仅是替换
#define MY_STRING char *
9、conts关键字
如果 const 写在指针类型的左边, 那么意味着 指向的内存空间中的值 不能改变
但是 指针的指向 可以改变.
(同上)如果 const 写在指针的数据类型 和 *号 之间,那么意味着 指向的内存空间中的值 不能改变
但是 指针的指向 可以改变.
如果 const 写在指针的右边 (数据类型 * const), 那么意味着 指针的指向 不可以改变,
但是 指向的内存空间中的值 可以改变
规律:
如果 const 写在指针变量名的旁边 , 那么 指针的指向不能变, 而 指向的内存空间的值 可以变
如果 const 写在 数据类型的左边 或者 右边, 那么 指针的指向可以改变,但是 指向的内存空间 不能改变
但是 指针的指向 可以改变.
(同上)如果 const 写在指针的数据类型 和 *号 之间,那么意味着 指向的内存空间中的值 不能改变
但是 指针的指向 可以改变.
如果 const 写在指针的右边 (数据类型 * const), 那么意味着 指针的指向 不可以改变,
但是 指向的内存空间中的值 可以改变
规律:
如果 const 写在指针变量名的旁边 , 那么 指针的指向不能变, 而 指向的内存空间的值 可以变
如果 const 写在 数据类型的左边 或者 右边, 那么 指针的指向可以改变,但是 指向的内存空间 不能改变