黑马程序员——C语言之 指针
2015-08-10 17:44
369 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
24.地址
①计算机硬件系统内部存储器,拥有大量的存储单元(单位容量为1字节)。为了方便管理,必须为每一个存储单元编号,这个编号就是存储单元的“地址”,每个存储单元都有一个惟一的地址。
内存地址——内存中存储单元编号
②在地址所标识的存储单元中存放数据。
注意:内存单元的地址与内存单元中的数据是两个完全按不同的概念。
变量地址——系统分配给变量的内存单元的起始地址
25.指针
内存单元的标号也叫做地址。既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。
内存单元的指针和内存单元的内容是两个不同的概念。
指针实质就是地址。
总结:对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元的内容。
①使用指针的好处
1)为函数提供膝盖调用变量的灵活手段;
2)让函数有多个返回值;
3)可以改善某些子程序的效率;
4)为动态数据结构(如二叉树,链表)提供支持;
②变量的存取方式:
存取方式分为两种:直接存取和间接存取
1)直接存取:变量的赋值和取值(通过变量名来存取值);
2)间接存取:通过指针(地址)间接操作完成;
③为什么要区分类型:
在同一种编译器环境下,一个指针变量所占用的内存空间是固定的。16位,任何指针变量都只占2个字节,32位4个字节,64位8个字节。
25.指针变量
在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。
注意:
严格意义上说,指针是一个地址,是一个常量
针变量是存放一个地址,是一个变量
①定义一个指针变量
一般形式为:类型说明符 *变量名;
其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。
int *p; //定义了一个指针变量,变量名是p。int表示,p只能存放一个int类型变量的地址
②指针变量定义注意事项:
1)“*”必须有;
2)不能存放那个数值或者字符之类;
3)指针变量,归根结底还是变量,也有全局和局部之分;
③指针的使用
定义指针变量——>初始化指针变量——>使用(使用指针变量间接的存取内存单元的值)
int *p = &a; 等价于 :int *p; p = &a;
指针初始化时,“=”的右操作数必须为内存中数据的地址,不可以是变量,也不可以直接用整型地址值(但是int*p=0;除外,该语句表示指针为空)。此时,*p只是表示定义的是个指针变量,并没有间接取值的意思。
1)定义同时初始化
a.完全初始化
int a = 10;
int *p = &a; //用a的地址初始化p这个指针变量,另一种描述方法:p指向了a
int *p1 = &a,*p2 = &a //p1 p2都指向了a
b.部分初始化
int *p2 = &b,*p4;
p4 = &b;
2)先定义后初始化
int *p5;
p5 = NULL;
3)如果定义了一个指针变量,但是暂时不知道让这个指针指向谁
int *p4 = NULL; //NULL是空(0)
int *p5 = 0; //空
注意:多个指针可以同时指向同一个地址
④指针的赋值
int *p;
int a;
int b[1];
p = &a;
p = b;
指针的赋值,“=”的左操作数可以是*p,也可以是p。
当“=”的左操作数是*p时,改变的是p所指向的地址存放的数据;
当“=”的左操作数是p时,改变的是p所指向的地址。
数组的变量名b表示该数组的首地址,因此p=b;也是正确的
⑤应用场景:
1)在被调函数中可以修改主调函数中的变量的值;
2)让函数可以有多个返回值;
26.二级指针
如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。也称为“二级指针”
27.数组指针
int *p; p = a; 等价于 int*p; p = &a[0]; 等价于 int *p = a; 等价于 int *p = &a[0];
①数组元素指针:指针变量可以指向数组元素(把某一元素的地址放到一个指针变量中),所谓数组元素的指针就是数组元素的地址。可以用一个指针变量指向一个数组元素。
②int a[] = {1,2,3,4};int *p = a; p+1 为数组下一个元素地址,p-1为数组上一个元素的地址
③int a[] ={1,2,3,4}; int *p = a; *p++ = *p ,p++ //此时 *p++ = 1,p再自加1,下一次*p = 2
++ -- 只能作用于变量,不能作用于常量。如*a++就是错误的。
④获取a[i]地址
1)&a[i]
2) a+i;
3) int *p = a; p+i;
获取a[i]的值
1)a[i]
2)*(a+i)
3)int *p = a; *(p+i);
4)*(&a[i])
28.指针数组
一个数组的元素值为指针则是指针数组。指针数组是一组有序的指针的集合。指针数组的是所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。指针数组说明的一般形式为:
类型说明符 *数组名[数组长度]
int *pa[3]; //表示pa是一个指针数组,它有三个数组元素,每一个元素值都是一个指针,指向整形变量。
29.指针变量之间的运算
int a[] = {1,2,3,4};
int *p = a;
int *p1 = &a[1];
①减法运算
正常的指针之间减法无意义,只有当两个指针同时指向一个数组的时候才有意义,用来检查两个元素是否连续,相处多少个地址。
p1 - p = 3 ,差3个位
p - p1 = -3 ,p在地位,p1在高位,差3个位
②关系运算
p1 > p = 1 p1在高位
p1 > p = 0 p在高位
30.数组名访问二维数组
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
①列地址
a[0] 为第一行第一个元素的地址 ,a[0]+1 为第一行第二个元素的地址。
a[0] = &a[0][0],a[0]+1 = &a[0][1]
②行地址
a为第一行首地址。
a+1为第二行首地址,其等于a[1]首地址(&a[1][0])。
40.指针函数
在C语言中允许一个函数的返回值时一个指针(地址),这种返回指针的函数成为指针函数。
①定义: 类型说明符 *函数名(形参表){函数体}
//在函数名前加了“*”号表明这是一个指针型函数,即返回值是一个指针
②调用函数的时候形参变量是新分配的空间,实参和形参只是指传递,没有传递地址。需要返回地址的时候,就需要用到指针函数。
41.函数指针
在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。
我们可以把函数的这个首地址(或入口地址)赋予一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针成为“函数指针变量”。
①定义:返回值类型 (*变量名)(函数的参数);
int sum(int a,int b){} ——>函数指针:int (*p1)(int a,int b); //定义了一个函数指针p1,p1可以存放返回值为int,并且有两个形参,形参类型都
是int的函数的地址;
定义函数指针的时候,可以不用写形参名
②初始化:p1 = sum; //sum存放的就是函数在内存中的首地址
24.地址
①计算机硬件系统内部存储器,拥有大量的存储单元(单位容量为1字节)。为了方便管理,必须为每一个存储单元编号,这个编号就是存储单元的“地址”,每个存储单元都有一个惟一的地址。
内存地址——内存中存储单元编号
②在地址所标识的存储单元中存放数据。
注意:内存单元的地址与内存单元中的数据是两个完全按不同的概念。
变量地址——系统分配给变量的内存单元的起始地址
25.指针
内存单元的标号也叫做地址。既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。
内存单元的指针和内存单元的内容是两个不同的概念。
指针实质就是地址。
总结:对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元的内容。
①使用指针的好处
1)为函数提供膝盖调用变量的灵活手段;
2)让函数有多个返回值;
3)可以改善某些子程序的效率;
4)为动态数据结构(如二叉树,链表)提供支持;
②变量的存取方式:
存取方式分为两种:直接存取和间接存取
1)直接存取:变量的赋值和取值(通过变量名来存取值);
2)间接存取:通过指针(地址)间接操作完成;
③为什么要区分类型:
在同一种编译器环境下,一个指针变量所占用的内存空间是固定的。16位,任何指针变量都只占2个字节,32位4个字节,64位8个字节。
25.指针变量
在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。
注意:
严格意义上说,指针是一个地址,是一个常量
针变量是存放一个地址,是一个变量
①定义一个指针变量
一般形式为:类型说明符 *变量名;
其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。
int *p; //定义了一个指针变量,变量名是p。int表示,p只能存放一个int类型变量的地址
②指针变量定义注意事项:
1)“*”必须有;
2)不能存放那个数值或者字符之类;
3)指针变量,归根结底还是变量,也有全局和局部之分;
③指针的使用
定义指针变量——>初始化指针变量——>使用(使用指针变量间接的存取内存单元的值)
int *p = &a; 等价于 :int *p; p = &a;
指针初始化时,“=”的右操作数必须为内存中数据的地址,不可以是变量,也不可以直接用整型地址值(但是int*p=0;除外,该语句表示指针为空)。此时,*p只是表示定义的是个指针变量,并没有间接取值的意思。
1)定义同时初始化
a.完全初始化
int a = 10;
int *p = &a; //用a的地址初始化p这个指针变量,另一种描述方法:p指向了a
int *p1 = &a,*p2 = &a //p1 p2都指向了a
b.部分初始化
int *p2 = &b,*p4;
p4 = &b;
2)先定义后初始化
int *p5;
p5 = NULL;
3)如果定义了一个指针变量,但是暂时不知道让这个指针指向谁
int *p4 = NULL; //NULL是空(0)
int *p5 = 0; //空
注意:多个指针可以同时指向同一个地址
④指针的赋值
int *p;
int a;
int b[1];
p = &a;
p = b;
指针的赋值,“=”的左操作数可以是*p,也可以是p。
当“=”的左操作数是*p时,改变的是p所指向的地址存放的数据;
当“=”的左操作数是p时,改变的是p所指向的地址。
数组的变量名b表示该数组的首地址,因此p=b;也是正确的
⑤应用场景:
1)在被调函数中可以修改主调函数中的变量的值;
2)让函数可以有多个返回值;
26.二级指针
如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。也称为“二级指针”
27.数组指针
int *p; p = a; 等价于 int*p; p = &a[0]; 等价于 int *p = a; 等价于 int *p = &a[0];
①数组元素指针:指针变量可以指向数组元素(把某一元素的地址放到一个指针变量中),所谓数组元素的指针就是数组元素的地址。可以用一个指针变量指向一个数组元素。
②int a[] = {1,2,3,4};int *p = a; p+1 为数组下一个元素地址,p-1为数组上一个元素的地址
③int a[] ={1,2,3,4}; int *p = a; *p++ = *p ,p++ //此时 *p++ = 1,p再自加1,下一次*p = 2
++ -- 只能作用于变量,不能作用于常量。如*a++就是错误的。
④获取a[i]地址
1)&a[i]
2) a+i;
3) int *p = a; p+i;
获取a[i]的值
1)a[i]
2)*(a+i)
3)int *p = a; *(p+i);
4)*(&a[i])
28.指针数组
一个数组的元素值为指针则是指针数组。指针数组是一组有序的指针的集合。指针数组的是所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。指针数组说明的一般形式为:
类型说明符 *数组名[数组长度]
int *pa[3]; //表示pa是一个指针数组,它有三个数组元素,每一个元素值都是一个指针,指向整形变量。
29.指针变量之间的运算
int a[] = {1,2,3,4};
int *p = a;
int *p1 = &a[1];
①减法运算
正常的指针之间减法无意义,只有当两个指针同时指向一个数组的时候才有意义,用来检查两个元素是否连续,相处多少个地址。
p1 - p = 3 ,差3个位
p - p1 = -3 ,p在地位,p1在高位,差3个位
②关系运算
p1 > p = 1 p1在高位
p1 > p = 0 p在高位
30.数组名访问二维数组
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
①列地址
a[0] 为第一行第一个元素的地址 ,a[0]+1 为第一行第二个元素的地址。
a[0] = &a[0][0],a[0]+1 = &a[0][1]
②行地址
a为第一行首地址。
a+1为第二行首地址,其等于a[1]首地址(&a[1][0])。
40.指针函数
在C语言中允许一个函数的返回值时一个指针(地址),这种返回指针的函数成为指针函数。
①定义: 类型说明符 *函数名(形参表){函数体}
//在函数名前加了“*”号表明这是一个指针型函数,即返回值是一个指针
②调用函数的时候形参变量是新分配的空间,实参和形参只是指传递,没有传递地址。需要返回地址的时候,就需要用到指针函数。
41.函数指针
在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。
我们可以把函数的这个首地址(或入口地址)赋予一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针成为“函数指针变量”。
①定义:返回值类型 (*变量名)(函数的参数);
int sum(int a,int b){} ——>函数指针:int (*p1)(int a,int b); //定义了一个函数指针p1,p1可以存放返回值为int,并且有两个形参,形参类型都
是int的函数的地址;
定义函数指针的时候,可以不用写形参名
②初始化:p1 = sum; //sum存放的就是函数在内存中的首地址
相关文章推荐
- android面试
- 年度催泪之作:2015中国程序员生存报告
- 百度测试开发面试题
- 面试题收集
- 面试题集锦---BY算法导论小组
- 黑马程序员--IO流之字符流
- PHP的文件操作与算法实现的面试题示例
- 黑马程序员——面向对象概述+类与对象的关系-第8天
- Mac Pro 提高效率 快捷键 程序员
- 关于游戏程序猿的职业生涯规划
- 题解分析及总结:经典逻辑面试题“假设有一个池塘,里面有无穷多的水,现有2个空水壶,如何使用少于15L的水,用2个水壶从池塘里取得3升水”
- 99%的海量数据处理面试题
- Android程序员必读电子书推荐
- 程序员学炒股(7) 股指期货收盘价对第二天开盘价有影响吗?
- 为什么想得慢的人能赢,程序员又如何
- 程序员常去的14个顶级开发社区
- 为什么程序员的业余项目大多都死了?
- 黑马程序员——代理
- 漫谈程序员(五)20年资深程序员编程经验分享
- 漫谈程序员(五)20年资深程序员编程经验分享