1指针和地址有什么区别?
指针:指针有类型 地址:没有类型,需要强制类型转换才能够赋值给指针变量
int* p = (int *)0x44fc28;
2.空指针
2.1注意:指针使用之前必须要有初始值(初始化)
2.2有的时候我们一时半会没有用到,但是有一个初始值,给一个NULL
int* p = NULL;
2.3我们不会直接给指针变量赋值为整数因为由于数字比较小,系统本身已经占用这块内存区域,系统本身内存数据不允许访问
3.多级指针(一般最多使用到三级,为什么不实用4,5,6。。级别,原因和嵌套为什么不超过三次一样)
3.1指针变量也是变量,同样占据了内存空间,同样有地址,
因此可以用一个指针指向它,这就称之为二级指针
多级指针的作用:删除链表、动态分配内存给二维数组等等......
3.2演示案例
void main(){
int a = 100;
int b = 200;
//a变量的地址
int* p1 = &a;
//打印指针的地址
printf("p1地址:%#x\n", &p1);
//二级指针
int** p2 = &p1;
//p2保存的数据是p1地址,*p2上的数据是p1上面数据,
//p1保存的数据是a的地址,**p2实际上就是a的值
**p2 = 1000;
printf("二级指针地址:%#x\n",&p2);
printf("a的值:%d", a);
getchar();
}
4.指针的运算(赋值运算、算术运算)
4.1演示案例
void main(){
//赋值运算
//int a = 200;
//int* p = &a;
//算数运算(+ - * /)
//数组
//总结一:ids常量指针,存储的是数组的首地址
//总结二:数组在内存中排列是连续不断(线性排列)
int ids[] = {23,15,67,38,99,70};
//打印数组
//printf("数组:%#x\n", ids);
//数组第一个元素地址
//printf("数组第一个元素地址:%#x\n",&ids[0]);
//总结:p++每次向前移动sizeof(数据类型)个字节
int* p = ids;
//p++;
//printf("地址:%#x 值:%d", p, *p);
//遍历数组
//传统方式
//int i = 0;
//for (; i < 6; i++){
//printf("值:%d\n", ids[i]);
//}
//通过指针遍历
for (; p < ids + 6; p++){
printf("地址:%#x 值:%d\n",p, *p);
}
//注意:让指针递增或者递减,一般情况下只有在数组遍历的时候才有意义,
//基于数组在内存中是线性排列的方式(连续不断)
//注意:有可能会导致访问到其他的内存区域(例如:系统程序、第三方程序)
getchar();
}
5.指针运算(通过使用指针循环给数组赋值)
5.1案例演示
void main(){
int ids[6];
int* p = ids;
//传统写法(高级写法)
//赋值
//int i = 0;
//for (; i < 6; i++)
//{
//ids[i] = i;
//}
//输出
//int j = 0;
//for (; j < 6; j++){
//printf("值:%d\n", ids[j]);
//}
//指针方式赋值
int i = 0;
for (; p < ids + 6; p++){
*p = i;
i++;
}
int j = 0;
for (; j < 6; j++){
printf("值:%d\n", ids[j]);
}
getchar();
}
6.数组内部指针的加减
6.1案例演示
void main(){
int ids[] = { 23, 15, 67, 38, 99, 70 };
int* p = ids;
p = p + 3;
printf("值:%d 地址:%#x\n", *p, p);
p = p - 2;
printf("值:%d 地址:%#x\n", *p, p);
getchar();
}
7.指针运算-指针大小比较
7.1指针大小比较:都是在遍历数组的时候运用,其他情况下没什么用
7.2指针相等比较:指针地址相等,并不代表值相等,因为指针有类型
8. 指针运算-指针和数组的几种写法
8.1案例演示
void main(){
int ids[] = { 23, 15, 67, 38, 99, 70 };
int i = 0;
for (; i < 6; i++){
//输出-高级写法(常规写法)
//printf("%d %#x\n", ids[i], &ids[i]);
//之前分析了ids就是常量指针,就是一个首地址
//以下分析是取地址
//分析:ids是首地址
//ids+0 等价于 &ids[0]
//ids+1 等价于 &ids[1]
//以此类推......
//总结:ids+i 等价于 &ids[i]
//分析取值
//*(ids+0) 等价于 ids[0]
//*(ids+1) 等价于 ids[1]
//以此类推......
//总结:*(ids+i) 等价于 ids[i]
printf("%d %#x\n",*(ids+i),ids+i);
}
printf("\n\n");
int* p = ids;
i = 0;
for (; i < 6; i++){
printf("%d %#x\n", p[i], &p[i]);
//printf("%d %#x\n", *(p + i), p + i);
}
getchar();
}
9.指针与二维数组
9.1演示案例
void main(){
//两行三列-二维数组
int ids[2][3] = { 23, 15, 67, 38, 99, 70 };
//遍历二维数组:外层循环控制行,内层循环控制列
int i = 0;
for (; i < 2; i++){
int j = 0;
for (; j < 3; j++){
printf("值:%d 地址:%#x ", ids[i][j],&ids[i][j]);
}
printf("\n");
}
printf("\n");
printf("\n");
//地址相同,并不代表值相同
//总结
//ids代表的是一个行指针,指向一个有三个元素的数组,大小12
//&ids代表的是一个二维数组指针,当前二维数组6个元素,长度24
//*ids代表的是一个指向该二维数组的数据类型的指针(相当于首地址:&ids[0][0])
printf("ids:%#x &ids:%#x *ids:%#x\n",ids,&ids,*ids);
printf("长度:%d 长度:%d 长度:%d\n", sizeof(*ids), sizeof(*&ids), sizeof(**ids));
printf("值:%d\n", **ids);
//推导过程分析
//打印第二行,第二列
printf("%d\n",ids[1][2]);
//推导
//ids + 0 代表第一行 第一行的第一个值
//ids + 1 第二行(下一行) 第二行的第一个值
//以此类推:ids + i
//取每一行第一个元素的指针:*(ids+i)
//第一行第一个元素指针:*(ids+0)
//第二行第一个元素指针:*(ids+1)
//以此类推:*(ids+i)
//继续推理
//取第一行第一个指针:*ids + 0
//取第一行第二个指针:*ids + 1
//取第一行第三个指针:*ids + 2
//以此类推:*ids + j
//继续推理
//取第一行第二个指针:*(ids+0)+1
//取第二行第二个指针:*(ids+1)+1
//以此类推:*(ids+i)+j(这个公式获取的是地址,是一个指针变量)
//*(*(ids+i)+j)
printf("%d", *(*(ids+1)+2));
getchar();
}
指针:指针有类型 地址:没有类型,需要强制类型转换才能够赋值给指针变量
int* p = (int *)0x44fc28;
2.空指针
2.1注意:指针使用之前必须要有初始值(初始化)
2.2有的时候我们一时半会没有用到,但是有一个初始值,给一个NULL
int* p = NULL;
2.3我们不会直接给指针变量赋值为整数因为由于数字比较小,系统本身已经占用这块内存区域,系统本身内存数据不允许访问
3.多级指针(一般最多使用到三级,为什么不实用4,5,6。。级别,原因和嵌套为什么不超过三次一样)
3.1指针变量也是变量,同样占据了内存空间,同样有地址,
因此可以用一个指针指向它,这就称之为二级指针
多级指针的作用:删除链表、动态分配内存给二维数组等等......
3.2演示案例
void main(){
int a = 100;
int b = 200;
//a变量的地址
int* p1 = &a;
//打印指针的地址
printf("p1地址:%#x\n", &p1);
//二级指针
int** p2 = &p1;
//p2保存的数据是p1地址,*p2上的数据是p1上面数据,
//p1保存的数据是a的地址,**p2实际上就是a的值
**p2 = 1000;
printf("二级指针地址:%#x\n",&p2);
printf("a的值:%d", a);
getchar();
}
4.指针的运算(赋值运算、算术运算)
4.1演示案例
void main(){
//赋值运算
//int a = 200;
//int* p = &a;
//算数运算(+ - * /)
//数组
//总结一:ids常量指针,存储的是数组的首地址
//总结二:数组在内存中排列是连续不断(线性排列)
int ids[] = {23,15,67,38,99,70};
//打印数组
//printf("数组:%#x\n", ids);
//数组第一个元素地址
//printf("数组第一个元素地址:%#x\n",&ids[0]);
//总结:p++每次向前移动sizeof(数据类型)个字节
int* p = ids;
//p++;
//printf("地址:%#x 值:%d", p, *p);
//遍历数组
//传统方式
//int i = 0;
//for (; i < 6; i++){
//printf("值:%d\n", ids[i]);
//}
//通过指针遍历
for (; p < ids + 6; p++){
printf("地址:%#x 值:%d\n",p, *p);
}
//注意:让指针递增或者递减,一般情况下只有在数组遍历的时候才有意义,
//基于数组在内存中是线性排列的方式(连续不断)
//注意:有可能会导致访问到其他的内存区域(例如:系统程序、第三方程序)
getchar();
}
5.指针运算(通过使用指针循环给数组赋值)
5.1案例演示
void main(){
int ids[6];
int* p = ids;
//传统写法(高级写法)
//赋值
//int i = 0;
//for (; i < 6; i++)
//{
//ids[i] = i;
//}
//输出
//int j = 0;
//for (; j < 6; j++){
//printf("值:%d\n", ids[j]);
//}
//指针方式赋值
int i = 0;
for (; p < ids + 6; p++){
*p = i;
i++;
}
int j = 0;
for (; j < 6; j++){
printf("值:%d\n", ids[j]);
}
getchar();
}
6.数组内部指针的加减
6.1案例演示
void main(){
int ids[] = { 23, 15, 67, 38, 99, 70 };
int* p = ids;
p = p + 3;
printf("值:%d 地址:%#x\n", *p, p);
p = p - 2;
printf("值:%d 地址:%#x\n", *p, p);
getchar();
}
7.指针运算-指针大小比较
7.1指针大小比较:都是在遍历数组的时候运用,其他情况下没什么用
7.2指针相等比较:指针地址相等,并不代表值相等,因为指针有类型
8. 指针运算-指针和数组的几种写法
8.1案例演示
void main(){
int ids[] = { 23, 15, 67, 38, 99, 70 };
int i = 0;
for (; i < 6; i++){
//输出-高级写法(常规写法)
//printf("%d %#x\n", ids[i], &ids[i]);
//之前分析了ids就是常量指针,就是一个首地址
//以下分析是取地址
//分析:ids是首地址
//ids+0 等价于 &ids[0]
//ids+1 等价于 &ids[1]
//以此类推......
//总结:ids+i 等价于 &ids[i]
//分析取值
//*(ids+0) 等价于 ids[0]
//*(ids+1) 等价于 ids[1]
//以此类推......
//总结:*(ids+i) 等价于 ids[i]
printf("%d %#x\n",*(ids+i),ids+i);
}
printf("\n\n");
int* p = ids;
i = 0;
for (; i < 6; i++){
printf("%d %#x\n", p[i], &p[i]);
//printf("%d %#x\n", *(p + i), p + i);
}
getchar();
}
9.指针与二维数组
9.1演示案例
void main(){
//两行三列-二维数组
int ids[2][3] = { 23, 15, 67, 38, 99, 70 };
//遍历二维数组:外层循环控制行,内层循环控制列
int i = 0;
for (; i < 2; i++){
int j = 0;
for (; j < 3; j++){
printf("值:%d 地址:%#x ", ids[i][j],&ids[i][j]);
}
printf("\n");
}
printf("\n");
printf("\n");
//地址相同,并不代表值相同
//总结
//ids代表的是一个行指针,指向一个有三个元素的数组,大小12
//&ids代表的是一个二维数组指针,当前二维数组6个元素,长度24
//*ids代表的是一个指向该二维数组的数据类型的指针(相当于首地址:&ids[0][0])
printf("ids:%#x &ids:%#x *ids:%#x\n",ids,&ids,*ids);
printf("长度:%d 长度:%d 长度:%d\n", sizeof(*ids), sizeof(*&ids), sizeof(**ids));
printf("值:%d\n", **ids);
//推导过程分析
//打印第二行,第二列
printf("%d\n",ids[1][2]);
//推导
//ids + 0 代表第一行 第一行的第一个值
//ids + 1 第二行(下一行) 第二行的第一个值
//以此类推:ids + i
//取每一行第一个元素的指针:*(ids+i)
//第一行第一个元素指针:*(ids+0)
//第二行第一个元素指针:*(ids+1)
//以此类推:*(ids+i)
//继续推理
//取第一行第一个指针:*ids + 0
//取第一行第二个指针:*ids + 1
//取第一行第三个指针:*ids + 2
//以此类推:*ids + j
//继续推理
//取第一行第二个指针:*(ids+0)+1
//取第二行第二个指针:*(ids+1)+1
//以此类推:*(ids+i)+j(这个公式获取的是地址,是一个指针变量)
//*(*(ids+i)+j)
printf("%d", *(*(ids+1)+2));
getchar();
}