/*** C语言高级编程 之 指针 ***/
注: 1.32为机上指针占四个字节 4 x 8byte == 32
2.内存:无数据类型 --- 程序:以已知数据类型的方式去访问内存
3.内存是线性唯一的无符号的整数
4.指针存放谁,就指向谁
printf("%d\n",*p) --- *p 指针的使用方式
1. 定义:
指针是c的灵魂
指针: 地址 + 内存操作方式
指针变量:存放一个指针(地址)的变量
指针的约定俗称:把指针变量统称为指针
2. 声明:
指针:1.地址 0 2.从这个地址开始的操作方式(指针的数据类型)
指针变量:一个存放 指针 的变量(int a;a=3)
指针的类型 * 指针变量名;
int a=1111;
int *p =&a;
对变量名&a:
1).得到的是变量的首地址
2).相当于一个指针,指向其本身的一个指针
3. 区别:
int *p;
指针变量的类型: 把指针变量去掉之后的类型
指针指向的类型: 把 * 指针变量 去掉之后的类型
指针变量的值: 指针变量p的值( &a )
指针指向的值: a的值同时也是*p
int *q;
*i = 3; 野指针( 非法指针 ) 或者改变了不能改变的内存空间 --- 段错误
4. 指针的运算 指针变量与一个整数相加减并不是用指针变量里的地址直接加减这个整数。这个整数的单位不是byte 而是元素的个数。
1)指针无位运算;
2)加减运算 不会影响数据类型
p1+n // 偏移数据类型
p2-p1 // p2--p1 之间数据类型的个数
p2+p1 (无意义)
3)强制类型转换 功能强大什么都可以转换
int a = 258;
char *p = (char *)&a;
4)比较运算
p1 > p2
p1 != p2
与空指针比较:
NULL == p1
p1 != NULL
5. 指针与字符串
char a[20] = "hello";
char *p = "hello";
6. 多级指针
指针变量:存放 指针(地址) 的变量
多级指针:存放 指向一个指针 的变量
int a =3;
int *p = &a;
int* *P1 =&p;
int** *p2 =&p1;
7. 指针与数组
1)复习数组:
数组: 一段连续的内存空间,存放着相同的数据类型
数组在内存的 都是一维的,没有多维的概念
数组的定义:
int a[5]; //定长数组
int a[]={1,2,3,4,5};//不定长数组,该定义必须初始化
int n =5; int a[n];//变长数组,该数组定义时,必须确定n的值
int a[0]; //零长数组
数组的初始化:
完全
int a[5]={1,2,3,4,5};
不完全
顺序初始化:
int a[5]={1,2}; //其他没有被初始化的,由编译器初始化成0
指定初始化:
int a[5]={[0]=1,[2]=3};
不初始化
普通变量: 是内存中原有的值,未知
全局变量:由编译器初始化成0
2)数组的使用:
数组的单个使用:
数组名[下标]; a[1]; int a[n];下标范围[0-n-1]
数组的整体使用:
内存操作方式:
比如:
memset(a,0,sizeof(a)); // 数组初始化,将参数 a 所指向的内存空间以 sizeof(a)个字节数以参数 0 填入,然后返回指向 a 的指针
bzero(a,0); // 将参数 a 的内容 全部设为 0
memcpy(void *dest,const void *src,size_t n); // 用来拷贝 src 所指向的内存内容前 n 个字节到 dest所指向的内存地址上,会完整地复制 n 个字节,不会因为遇到字符串结束标志 '\0' 而结束
0). int a[10];
a: 数组名 sizeof() 首地址首元素 &a[0] = a; a是指针常量
&a 是整个数组的首地址,a是数组首元素的首地址,其值相同但意义不同。
1). 一维数组
int a[5]={1,2,3,4,5};
int *p =a;
数组名:a 相当于一个指针,指向数组中的第0个元素 (相当于一个指针,指向其本身,这里相当于一个指向一维数组的指针)
对数组名取地址:&a相当于一个指针,指向它本身,也就是指向整个数组的指针
&a[i] == a+i &a + 1 偏移整个数组空间 a + 1 == &a[0] + 1 偏移一个元素类型
a[i] == *(a+i) == *(i+a) == i[a] == *(p+i) == *(i+p) == p[i] == i[p];
int a[10] = {11,2,5,4,7,2};
int *p = a; //a == &a[0]
int (*q)[10] = &a; // 数组指针,用来指向一个数组
2). 指针与二维数组
数组在内存中没有多维的概念:只有一维(内存是一维的)
int a[2][3]={1,2,3,4,5,6}; // a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
int (*p)[3] = a;
a[i][j] == (*(a+i))[j] == *(*(a+i)+j) == *(a[i]+j) == i[a][j]
int (*p)[3] = a; // 数组指针 --- a pointer to an array,即指向数组的指针
int *p[3]; // 指针数组 --- array of pointers,即用于存储指针的数组,也就是数组元素都是指针
数组名:a相当于一个指针:指向数组中的第0个元素,这里是一个一维数组
对数组名取地址:&a相当于一个指针,指向它本身,也就是指向整个二维数组的指针
a+i:相当于一个指针,指向数组中的第i个元素 ,这里是一个一维数组
*(a+i)+j:相当于一个指针,指向数组中的第i个元素中的第j个元素,这里指向一个整形
*(*(a+i)+j):就是该整形值
3). 指针与三维数组
int a[2][3][4]={ { {1,2,3,4} ,{5,6,7,8} ,{1,2,3,4}} , { {....},{....},{....} } };
a[i][j][k] = *(*(*(a+i)+j)+k)== i[a][j][k]==*(*(a[i]+j)+k) == *(a[i][j]+k)
数组名:a相当于一个指针:指向数组中的第0个元素,这里是一个二维数组
对数组名取地址:&a相当于一个指针,指向它本身,也就是指向整个三维数组的指针
a+i:相当于一个指针,指向数组中的第i个元素 ,这里指向一个二维数组
*(a+i)+j:相当于一个指针,指向数组中的第i个元素中的第j个元素,这里指向一个一维数组
*(*(a+i)+j)+k:相当于一个指针指向数组中第i个元素中的第j个元素中的第k个元素,这里指向一个整形
*(*(*(a+i)+j)+k):这里是一个整形值
8. void 指针:
void *p; // 使用时必须强转
p+1 ;// 偏移量 为1