5.指针与数组之间的关系
根据以上代码可知道:数组名被看作数组的第一个元素在数组中的首地址(仅在sizeof操作中例外,该操作给出的数组是整个数组的大小),数组名在表达式中被自动转换为一个指向数组第一个元素的指针常量。
数组名是指针,非常方便,但是丢失了数组的一个最重要的特点:数组大小,即数组的元素数量
C提供根据数组的存储地址访问数组元素的方法。上图中ar是数组首元素的地址,所以*ar是数组第一个元素ar[0],而ar+1是数组的第二个元素的地址,即*(ar+1)就是第二个元素ar[1]本身,指针加1,即地址i移动一个数组元素所占的字节数
c语言的下标运算符[ ]是以指针作为操作数的,ar[i]被编译系统解释为*(ar+i),即表示ar所指元素向后第i个元素,无论以下标方式或指针方式存取数组元素时,系统都是转换为指针方式
5.1数组名访问
5.2指针访问
ar[i]与p[i]的区别?
ar是数组名,p是一个指向首元素地址的指针变量
总结:指针的算术运算
1. 指针变量与整型量的加减表示移动指针,以指向当前目标前后的若干元素的地址。指针与整型量i 的加减等于指针值(地址)与i*(sizeof)(目标类型)积的加减,得出新的地址
2. 运算结果并不表示那有一个指针所规定的数据类型的变量,即使是对数组操作。这称作不对数组边界检查,指针的运算符很容易超出数组的边界 ,需要小心越界问题
5.5指针变量与const
const关键字修饰数组与变量,使其成为常数组和常变量,const也可以修饰指针变量;
const 与指针配合使用有两种作用,一是限制指针变量,二是限制指针变量所指的数据
1)限制指针变量本身,如:int * const p;
限制指针变量本身的意思是指针变量本身的值不能被修改,但指向可以改变,所以被const修饰的指针变量指针只能在定义中初始化,不能定义之后在赋值;
int* const ip;
int a = 10;
//ip = &a;会报错,因为const修饰的是指针变量,而指针变量不能改变
int a = 10;
int* const ip = &a;//const修饰指针变量本身定义时一定要初始化
*ip = 100;
//ip = &b;会报错,因为const修饰的是指针变量,而指针变量不能改变
2)限制指针变量指向的数据,如:const int*ip;int const*ip;
限制指针变量指向数据的意思是指针可以指向不同的变量(指针本身的值可以修改),但是不能用指针修改指针指向的数据的值
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int const* ip = NULL;//const修饰指向
ip = &a;//可以指向不同的变量。但是不能改变所指向的值
//*ip = 100;
ip = &b;
return 0;
}
3)也可以同时修饰指针变量和指针变量所指向的数据的值
const int *const ip;
int a = 10, b = 20;
const int* const ip;//error的定义
const int* const ip = &a;
int const* const ip2 = &a;
//*ip = 100;error const修饰指向的值也修饰了指针本身
//ip = &b;error
总结:区分const是限制的指针变量还是指针变量指向数据的值:沿着*号划一条线。如果const在*号的左侧即修饰指针指向的值,所以为指针指向为常量。如果在*号右边即修饰指针变量本身,所以为常性指针
4)const和函数形参:限定函数形参这样函数将不会修改实参指针所指向的值
5.6无类型指针void*(泛型指针)
void指针可以指向任意类型变量的地址。是指针都可以给void指针变量赋值,但是void指针赋给 其他类型指针时要进行类型的强制转换
int *ip =(int*)vp;
不允许对void指针进行算术运算
6.数组,指针和函数的综合
6.1用数组作为函数的形参,数组会退化成指针类型
void printf_Array(int br[], int m);//形参是一个未定义大小的数组
void printf_Array(int br[5], int m);//形参是一个已知大小的数组
void printf_Array(int* br, int m);//形参是一个指针
7.二级指针
指针可以指向普通类型的数据,例如int,double,char等,也可以指向指针类型的数据,例如int*,double*,char*等。如果一个指针指向的时另一个指针,我们就称它为二级指针,或者指向指针的指针