您的位置:首页 > 其它

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、指针

使用指针类型的返回值,可以让函数返回一个地址数据,让一个函数使用另外一个函数内部的静态局部变量。

面试题:编写函数,实现主函数中两个变量的内容交换。

#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. /* 野指针 */其他所有无效指针的统称
程序员必须保证:/* 程序里不出现野指针 */
所有/* 指针变量必须初始化 */
初始化的时候 * 没有参与赋值过程,被修改的是指针变量本身的存储区
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: