08:变量的作用域、初识指针
2016-10-15 23:16
309 查看
l 变量的作用域
C语言里的变量只能被一组特定的词语使用,这组词语叫做变量的作用域。
声明在函数内部的变量叫做局部变量,它的作用域是函数内部的所有语句。
声明在所有函数的外边的变量叫做全局变量,它的作用域包括程序中所有的语句。
简言之:
局部变量,即auto自动变量,使用完后会被系统回收,作用域在{ 语句块 }内。
全局变量,即外部变量,作用域在整个文件中。
Tips:跨文件使用变量,需要使用 extern int num; 可以实现跨文件使用num变量。
没有初始化的全局变量,会被自动初始化为0;
某个名称的全局变量在整个程序执行过程中只有一个。
如果全局变量或局部变量都能解决问题,那么优先使用局部变量。
存储区的使用不受作用域的限制,而受生命周期的限制。
存储区从被创造出来到被销毁的时间范围叫做:存储区的生命周期。
只要在生命周期的时间范围内,存储区就可以被使用。
全局变量生命周期:整个程序的执行时间。
局部变量生命周期:函数某一次执行的时间范围。
数组做为形参,可以实现跨函数使用存储区。(在生命周期条件内)
声明变量时,使用static关键字,把变量变成静态变量。所有静态变量的生命周期都是整个程序的运行时间。
static int num;
1、没有初始化的静态变量被初始化为0;
2、所有静态变量只在程序开始的时候初始化1次;
3、静态局部变量也可用来实现跨函数使用存储区(即变量的值),即不会被系统回收。
多文件编程时,静态全局变量作用域,只包含声明它的那个文件里的所有语句。
全局变量和局部变量可以重名,这个时候程序优先使用局部变量。
全局变量的利弊:
1、[利]:少数几个函数共享大量使用的变量时,非常有用;
2、[弊]:维护代码时,需检查所有使用的函数;
3、[弊]:赋值错误时,很难验证;
4、[弊]:很难被复用。
Tips:一般少用全局变量。
l 指针
[复习变量]
变量名:给一块内存起的一个名字。
变量四要素:
① 名字:代表存储区,也可以代表值使用;
② 类型:存储空间大小,存储格式;
③ 数值:整个存储区中的数值;
④ 地址:存储区中最小字节即为其地址,&加变量名表示。
指针的本质就是内存的地址,即指针用来记录地址。
32位系统的指针地址就是一个32位的数,1个字节=8个位,故:32位系统的指针地址所占就是4个字节。
指针变量:是存储指针内存地址的变量。
指针变量的值:是另外一个变量的值。
只有捆绑过的指针才可以使用。
在捆绑故偶的指针前加 * 可以表示捆绑变量的存储区,* 代表指针类型。
指针也分类型,不同类型的指针适合不同类型的存储区捆绑。如
int num = 10;
int *p_num;
p_num = #
Tips:指针的命名以p_开头,可以良好的区分普通变量与指针变量的名字。
可以在一条语句中声明多个同类型的指针变量,但是要在每个指针变量名前加 * 号。如
int *p_num, *p_num1, *p_num2;
指针的三点注意事项:
1、空指针里面记录空地址(宏NULL),如 *p_num = NULL;初始化为NULL空,这个地址数值就是0;
2、出了空指针以外的没有捆绑的指针,都叫野指针;
3、指针不能返回一个局部变量的地址。
切记:程序员要保证程序中不能出现野指针!所有指针变量必须进行初始化。
指针中的星号 * 不参与初始化的过程。
指针变量和普通变量之间的捆绑关系会随着程序的执行而不断变化。
可以把指针看做是变量的某种身份。
如果把数组中第一个存储区的地址记录到指针变量里,就可以通过指针找到数组里的任何存储区。
这个时候,可以认为指针简介捆绑了数组里的所有存储区。
地址数据可以参与一下计算:
1、地址+ 整数
2、地址– 整数
3、地址– 地址 (地址数据间做减法,结果是两个地址之间包含的捆绑存储区的个数)
地址数据加减整数n,事实上是加减的n个捆绑存储区的大小。
数组里面第一个存储区的地址加上下标,对应存储区的地址。如
arr[4] → *(arr+4)
p_num[4] → *(p_num+4)
数组中计算机内部对下包的处理,就是用前面的地址加上下标,然后在结果前面加 * 。
指针和数组名称的区别:
1、数组名称不可以赋值,指针变量可以赋值;
2、对他们做sizeof计算,结果不同;
3、对他们进行取地址操作,结果也不一样。
可以使用指针做循环变量,依次操作数组里的每个存储区。
指针的最常用的地方就是:跨函数使用存储区(也可以理解为:函数传参)。
跨函数使用存储区的方法有三:
1、数组形参(真正的形参其实还是指针)
2、静态局部变量(static)
3、指针
使用指针类型的返回值,可以让函数返回一个地址数据,让一个函数使用另外一个函数内部的静态局部变量。
面试题:编写函数,实现主函数中两个变量的内容交换。
const关键字:
声明指针变量的时候可以使用const关键字,作用:保护原始代码数据不被修改。
const后面的类型表示一个常量/常数字,即不可被更改/赋值。
如果const关键字写在了类型名称前,就表示不可以通过这个指针对捆绑的存储区进行赋值,但是可以对指针本身的存储区进行赋值。
当跨函数使用存储区的时候,如果存储区拥有者不希望别的函数修改自己的存储区,就应该采用上述办法在声明指针的时候加const关键字。
如果声明指针时,把const关键字加在指针变量名称前,就表示不可以对指针本身的存储区做赋值,但可以对捆绑存储区进行赋值。
可以在声明指针时,在 * 号前面加void表示类型名称,叫做 无类型指针。
这种指针可以和任意类型存储区捆绑,具体使用时再做强制类型转换:(数据类型)*p_num
面试题:
const int
a; //表示a为常量
int const
a; //表示a为常量,同上
const int
*p_a; //表示*p_a这个指针变量为常量,不可更改,地址p_a可更改
int *
const p_a; //表示p_a地址为常量,不可更改,*p_a指针变量可更改
完整版:
【变量的作用域】
程序中一个变量只能被某些语句使用,这些语句叫做这个变量的作用域
声明在函数里面的变量叫做/* 局部变量 */,局部变量的作用域包含函数里面的所有语句
声明在所有函数外边的变量叫做/* 全局变量 */,全局变量的作用域包含程序里的所有语句
没有初始化的全局变量自动被初始化为 0
全局变量和局部变量可以重名,这个变量名称优先代表局部变量
如果全局变量和局部变量都可以满足程序,要求应该/* 优先使用局部变量 */
存储区的使用不受作用域限制(可以跨函数使用存储区)
存储区的使用受到生命周期的限制
生命周期是一段时间,存储区只能在这段时间里才能使用
全局变量的生命周期是整个程序的执行时间
局部变量的生命周期是函数执行的某一次时间范围
如果一个函数多次执行则局部变量每次代表存储区都不同
使用 static 关键字可以声明 /* 静态变量 */
静态变量的声明周期一定是整个程序的执行时间
只要程序没有结束,则静态变量的存储区随时可以使用
静态局部变量在函数每次执行的时候对应的存储区都是同一个
没有初始化的静态变量,自动被初始化为 0
静态变量的初始化只在程序开始的时候执行 1 次
静态全局变量的作用域只包含了声明它的文件里面的所有语句(不可以跨文件使用静态全局变量)
【指针】
指针变量用来记录存储区的地址
只有记录有效地址的指针变量才可以使用
指针也分类型,不同类型的指针适合与不同的存储区捆绑
可以在一条语句中声明多个同类型指针变量,这个时候要在每个指针变量名称前单独加 *
没有记录有效地址的指针分成两类:
1. /* 空指针 */里面记录空地址( NULL 表示,这个地址的数值就是数字 0)
2. /* 野指针 */其他所有无效指针的统称
程序员必须保证:/* 程序里不出现野指针 */
所有/* 指针变量必须初始化 */
初始化的时候 * 没有参与赋值过程,被修改的是指针变量本身的存储区
C语言里的变量只能被一组特定的词语使用,这组词语叫做变量的作用域。
声明在函数内部的变量叫做局部变量,它的作用域是函数内部的所有语句。
声明在所有函数的外边的变量叫做全局变量,它的作用域包括程序中所有的语句。
简言之:
局部变量,即auto自动变量,使用完后会被系统回收,作用域在{ 语句块 }内。
全局变量,即外部变量,作用域在整个文件中。
Tips:跨文件使用变量,需要使用 extern int num; 可以实现跨文件使用num变量。
没有初始化的全局变量,会被自动初始化为0;
某个名称的全局变量在整个程序执行过程中只有一个。
如果全局变量或局部变量都能解决问题,那么优先使用局部变量。
存储区的使用不受作用域的限制,而受生命周期的限制。
存储区从被创造出来到被销毁的时间范围叫做:存储区的生命周期。
只要在生命周期的时间范围内,存储区就可以被使用。
全局变量生命周期:整个程序的执行时间。
局部变量生命周期:函数某一次执行的时间范围。
数组做为形参,可以实现跨函数使用存储区。(在生命周期条件内)
声明变量时,使用static关键字,把变量变成静态变量。所有静态变量的生命周期都是整个程序的运行时间。
static int num;
1、没有初始化的静态变量被初始化为0;
2、所有静态变量只在程序开始的时候初始化1次;
3、静态局部变量也可用来实现跨函数使用存储区(即变量的值),即不会被系统回收。
多文件编程时,静态全局变量作用域,只包含声明它的那个文件里的所有语句。
全局变量和局部变量可以重名,这个时候程序优先使用局部变量。
全局变量的利弊:
1、[利]:少数几个函数共享大量使用的变量时,非常有用;
2、[弊]:维护代码时,需检查所有使用的函数;
3、[弊]:赋值错误时,很难验证;
4、[弊]:很难被复用。
Tips:一般少用全局变量。
l 指针
[复习变量]
变量名:给一块内存起的一个名字。
变量四要素:
① 名字:代表存储区,也可以代表值使用;
② 类型:存储空间大小,存储格式;
③ 数值:整个存储区中的数值;
④ 地址:存储区中最小字节即为其地址,&加变量名表示。
指针的本质就是内存的地址,即指针用来记录地址。
32位系统的指针地址就是一个32位的数,1个字节=8个位,故:32位系统的指针地址所占就是4个字节。
指针变量:是存储指针内存地址的变量。
指针变量的值:是另外一个变量的值。
只有捆绑过的指针才可以使用。
在捆绑故偶的指针前加 * 可以表示捆绑变量的存储区,* 代表指针类型。
指针也分类型,不同类型的指针适合不同类型的存储区捆绑。如
int num = 10;
int *p_num;
p_num = #
Tips:指针的命名以p_开头,可以良好的区分普通变量与指针变量的名字。
可以在一条语句中声明多个同类型的指针变量,但是要在每个指针变量名前加 * 号。如
int *p_num, *p_num1, *p_num2;
指针的三点注意事项:
1、空指针里面记录空地址(宏NULL),如 *p_num = NULL;初始化为NULL空,这个地址数值就是0;
2、出了空指针以外的没有捆绑的指针,都叫野指针;
3、指针不能返回一个局部变量的地址。
切记:程序员要保证程序中不能出现野指针!所有指针变量必须进行初始化。
指针中的星号 * 不参与初始化的过程。
指针变量和普通变量之间的捆绑关系会随着程序的执行而不断变化。
可以把指针看做是变量的某种身份。
如果把数组中第一个存储区的地址记录到指针变量里,就可以通过指针找到数组里的任何存储区。
这个时候,可以认为指针简介捆绑了数组里的所有存储区。
地址数据可以参与一下计算:
1、地址+ 整数
2、地址– 整数
3、地址– 地址 (地址数据间做减法,结果是两个地址之间包含的捆绑存储区的个数)
地址数据加减整数n,事实上是加减的n个捆绑存储区的大小。
数组里面第一个存储区的地址加上下标,对应存储区的地址。如
arr[4] → *(arr+4)
p_num[4] → *(p_num+4)
数组中计算机内部对下包的处理,就是用前面的地址加上下标,然后在结果前面加 * 。
指针和数组名称的区别:
1、数组名称不可以赋值,指针变量可以赋值;
2、对他们做sizeof计算,结果不同;
3、对他们进行取地址操作,结果也不一样。
可以使用指针做循环变量,依次操作数组里的每个存储区。
指针的最常用的地方就是:跨函数使用存储区(也可以理解为:函数传参)。
跨函数使用存储区的方法有三:
1、数组形参(真正的形参其实还是指针)
2、静态局部变量(static)
3、指针
使用指针类型的返回值,可以让函数返回一个地址数据,让一个函数使用另外一个函数内部的静态局部变量。
面试题:编写函数,实现主函数中两个变量的内容交换。
#include <stdio.h> void swap(int *p_x, int *p_y); //函数显示声明 int main() { int a = 3, b = 7; swap(&a, &b); printf("a=3,b=7\n函数+指针交换值后:\na=%d,b=%d\n", a, b); return 0; } void swap(int *p_x, int *p_y) { int tmp = *p_x; *p_x = *p_y; *p_y = tmp; }
const关键字:
声明指针变量的时候可以使用const关键字,作用:保护原始代码数据不被修改。
const后面的类型表示一个常量/常数字,即不可被更改/赋值。
如果const关键字写在了类型名称前,就表示不可以通过这个指针对捆绑的存储区进行赋值,但是可以对指针本身的存储区进行赋值。
当跨函数使用存储区的时候,如果存储区拥有者不希望别的函数修改自己的存储区,就应该采用上述办法在声明指针的时候加const关键字。
如果声明指针时,把const关键字加在指针变量名称前,就表示不可以对指针本身的存储区做赋值,但可以对捆绑存储区进行赋值。
可以在声明指针时,在 * 号前面加void表示类型名称,叫做 无类型指针。
这种指针可以和任意类型存储区捆绑,具体使用时再做强制类型转换:(数据类型)*p_num
面试题:
const int
a; //表示a为常量
int const
a; //表示a为常量,同上
const int
*p_a; //表示*p_a这个指针变量为常量,不可更改,地址p_a可更改
int *
const p_a; //表示p_a地址为常量,不可更改,*p_a指针变量可更改
完整版:
#include <stdio.h> int main() { int a; // 一个整型数a int *a; // 一个指向整型数a的指针 int **a; // 一个指向指针a的指针 int a[10]; // 一个有10个整型数的数组a int *a[10]; // 一个有10个均指向整型数的指针数组a int (*a)[10]; // 一个指向有10个整型数数组的指针a int (*a)(int); // 一个指向函数a的指针 int (*a[10])(int); // 一个有10个指针的数组,指向一个整形函数并有一个整形参数 return 0; }
【变量的作用域】
程序中一个变量只能被某些语句使用,这些语句叫做这个变量的作用域
声明在函数里面的变量叫做/* 局部变量 */,局部变量的作用域包含函数里面的所有语句
声明在所有函数外边的变量叫做/* 全局变量 */,全局变量的作用域包含程序里的所有语句
没有初始化的全局变量自动被初始化为 0
全局变量和局部变量可以重名,这个变量名称优先代表局部变量
如果全局变量和局部变量都可以满足程序,要求应该/* 优先使用局部变量 */
存储区的使用不受作用域限制(可以跨函数使用存储区)
存储区的使用受到生命周期的限制
生命周期是一段时间,存储区只能在这段时间里才能使用
全局变量的生命周期是整个程序的执行时间
局部变量的生命周期是函数执行的某一次时间范围
如果一个函数多次执行则局部变量每次代表存储区都不同
使用 static 关键字可以声明 /* 静态变量 */
静态变量的声明周期一定是整个程序的执行时间
只要程序没有结束,则静态变量的存储区随时可以使用
静态局部变量在函数每次执行的时候对应的存储区都是同一个
没有初始化的静态变量,自动被初始化为 0
静态变量的初始化只在程序开始的时候执行 1 次
静态全局变量的作用域只包含了声明它的文件里面的所有语句(不可以跨文件使用静态全局变量)
【指针】
指针变量用来记录存储区的地址
只有记录有效地址的指针变量才可以使用
int num = 0; int *p_num; p_num = # *p_num = 10; //num结果为10在有效指针变量名称前使用 * 操作符可以表示地址对应的存储区
指针也分类型,不同类型的指针适合与不同的存储区捆绑
可以在一条语句中声明多个同类型指针变量,这个时候要在每个指针变量名称前单独加 *
没有记录有效地址的指针分成两类:
1. /* 空指针 */里面记录空地址( NULL 表示,这个地址的数值就是数字 0)
2. /* 野指针 */其他所有无效指针的统称
程序员必须保证:/* 程序里不出现野指针 */
所有/* 指针变量必须初始化 */
初始化的时候 * 没有参与赋值过程,被修改的是指针变量本身的存储区
相关文章推荐
- 有关js的变量作用域和this指针的讨论
- Go语言:变量声明,作用域,指针
- 有关js的变量作用域和this指针的讨论
- 黑马程序员IOS-C语言-指针、变量作用域
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- c笔记08---变量,栈,秒表练习,关键字 static,指针变量和变量的指针
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- C语言----变量及作用域 、 指针 、 指针和数组 、 进程空间 、 字符串
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 10:变量作用域、指针
- 返回指针的函数特性,和malloc的初识,全局变量的提示
- 有关js的变量作用域和this指针的讨论
- 20170214C语言提升08_指针_01变量及指针及数组
- 有关js的变量作用域和this指针的讨论
- C++中如何修改const变量 (指针)