基于唐老师 "C语言专题" 总结
指针
指针在本质上是一个变量
指针
需要用一定的内存空间
指针
用于保存内存地址的值
*号意义
指针声明时,*号表示所声明的变量为指针
指针使用时,*号表示取指针所指向的内存空间中的值
指针声明
指针初始化
指针是C中一种特殊的变量
指针所保存的值是内存的地址
可以通过指针修改内存中的任意地址内容
空指针
空指针用NULL表示,(void * )0
空指针常量:一个表示0值的整数常量
空指针:一个空指针常量赋给了一个有类型的指针变量
NULL是一个标准规定的
宏定义,用来表示空指针常量 <
(void *)0 >
常见的空指针一般指向0地址,即空指针的内部用全0表示
空指针判断 p == 0 || '\0' || NULL
数组
数组是相同类型变量的有序集合
数组在一片连续的内存空间中存储元素
数组元素的个数可以显示或隐式指定
数组名代表数组首元素地址
数组名可以看做一个
常量指针
数组名指向的是内存中数组首元素的起始位置
在表达式中数组名只能作为
右值使用
数组的地址需要用取地址符&才能得到
数组首元素的地址值与数组的地址值相同
数组首元素的地址和数组的地址是两个不同的概念
只有在下列场合中数组名不能看做常量指针
数组名作为sizeof操作符的参数
数组名作为&运算符的参数
指针VS数组
数组本质
数组是一段连续的内存空间
数组的空间大小为
sizeof(array_type)*array_size
数组的元素个数为
sizeof(array) /sizeof(*array)
数组名可看做指向数组第一个元素的常量指针
指针运算
指针是一种特殊的变量,与整数的运算规则为
当指针p指向一个同类型的数组的元素时;p+1将指向当前元素的下一个元素;p-1将指向当前元素的上一个元素
指针之间只支持加减法运算,且必须参与运算的指针类型必须相同
p1-p2; <-->
((unsigned int )p1 - (unsigned int )p2
) / sizeof(type)
只有当两个指针指向同一个数组中的元素时,指针相减才有意义,其意义为指针所指元素的下标差
当两个指针指向的元素不在同一个数组中时,结果未定义
指针也可以进行关系运算
< <= > =>
指针关系运算的前提是同时指向同一个数组中的元素
任意两个指针之间的比较运算(== !=)无限制
下标VS指针
从理论上而言,当指针以固定增量在数组中移动时,其效率高于下标产生的代码
当指针增量为1且硬件具有硬件增量模型时,表现更佳
注意:
现代编译器的生成代码优化率已大大提高,在固定增量时,下标形式的效率已经和指针形式相当
但从可读性和代码维护的角度来看,下标形式更佳
a和&a区别
a为数组首元素的地址
&a为整个数组的地址
a和&a的意义不同,其区别在于指针运算
a 表示数组的起始地址,(int ) a 表示将a的地址转化为一个整形数,(int)a + 1 表示普通的数值加法运算,(int *)((int)a + 1)表示把(int)a + 1转化为整型
指针的地址.该地址指向数组a(0)的第一个字节(从0计数),因为是int类型,
所以需要四个字节的解释,所以结果是a(0)的后三个和
a(1)的第一个字节组成
的值
C中,数组作为函数参数时,编译器将其编译成对应的指针
一般情况下,当定义的函数中有数组参数时,需要定义另一个参数来标识数组的大小
指针和数组的对比
数组声明时编译器自动分配一片连续内存空间
指针声明时只分配用于容纳指针的四字节空间
在作为函数参数时,数组参数和指针参数等价
数组名在多数情况下可以看做常量指针,其值不能改变
指针的本质是变量,保存的值被看做内存中的地址