- 学习指针的目的:
为了访问内存空间中的内容。
自己申请的空间全是经过格式化的,等于说你所能访问到的合法空间,全是经过类型有效格式化后的。 - 指针分为指针常量和指针变量
指针常量表示指针本身的内容不可变(指向不可变),因此,定义指针常量时必须同时初始化一个地址值
指针变量表示指针可以指向别处,因为指针本身是一个变量。
3.指针的本质就是一个(带类型)的地址值。和普通的地址值是不同的。
#include <stdio.h>
int main()
{
int a = 10;
int *p = &a;
printf("%d\n",p);//6356648
printf("%p\n",p);//0060FEA8
printf("%#x\n",p);//0060FEA8
printf("%d\n",*p);//10打印的是
//printf("%d\n",*(0x0060FEA8)); //error 带类型的地址和普通地址不同
printf("%d\n",*(int*)0x0060FEA8);//10类型带给了这个普通地址访问空间的能力。因为你通过类型告诉了编译器,这个地址能访问多大的空间。
return 0;
}
//此处的第十二行的错误是:0x0060FEA8这个地址只是一个普通的地址,不带类型的地址是无法访问其值的,访问的就是非法空间
- 指针跟数组关联使用
一个指向数组的指针,和该数组的数组名,到低有何异同?
数组的数组名就是数组的首地址,指向该数组的指针可以是一个变量,移动指针的位置,可以更改数组内部元素的值。
数组名就是数组首元素的地址。
#include <stdio.h>
int main()
{
int a[5] = {1,7,3,8,15};
int * p ;
p = a;
printf("a -> %p p -> %p \n", a, p);//此处打印的都是a的地址
printf("a[0] = %d *a = %d *p = %d \n",a[0],*a,*p);//*p、*a还有a[0]都是数组第一个元素的值
printf("*(p+2) = %d (*p+2) + 2 = %d\n",*(p+2),(*p+2) + 2);//*(p+2)是移动p指针,指向a[2]元素,而(*p+2) + 2则是给第一个元素+2后再+2
printf("将a[3]的8改变为28\n");
*(p+3) = 28;
printf("a[3] = %d *(p+3) = %d\n",a[3],*(p+3));此处对移动指针p,对*(p+3)即a[3]进行修改
}
/*输出结果是:
a -> 0060FE98 p -> 0060FE98
a[0] = 1 *a = 1 *p = 1
*(p+2) = 3 (*p+2) + 2 = 5
将a[3]的8改变为28
a[3] = 28 *(p+3) = 28
*/
- 传值分割显示
#include <stdio.h>
long func()
{
int a=5;
char b = 6;//C里面 char字符类型本质就是整型。是短短整型。
//char和int 可以相互无条件转换。
//&a int* +1 走4个字节
*((char *) &a + 1) = b;//此处是取a的地址,然后将其转为char *类型,然后将b这个数值存储在a后面
//那个地址上(此处是加上一个字节,因为是char*类型)就是(char *) &a + 1,再加上*号表示的是取那里的值,将b赋值进去的操作
return a;
}
int main()
{
int value = func();
char a = *((char*)&value);//此处是取value的地址,然后转为char*类型,取出其中a的值
char b = *((char*)&value + 1);//此处是取value的地址,转为char*类型,地址移动一个char*空间大小,指向char*类型后面的那个地址,取出里面的值赋给b
printf("%d,%d\n",a,b);
}
- 你所想的指向的数组中的基本(非最小)元素是什么类型的 ,就定义什么类型指针
int a[4][5][6] ;
int (*p)[5][6];
//需要特别注意的是,指向的数组中的基本单位是什么类型。 - 二维数组里面,数组名的操作
int main()
{
int a[2][3] = {
{1,2,3},
{4,5,6}
};
printf("sizeof a %d\n",sizeof(a));//输出24,6个int类型数据,4*6
printf("a = %p, a+1 = %p a[]+\n",a, a+1 );//a = 0060FE98, a+1 = 0060FEA4 输出a的地址和a地址+sizeof(int)*3
printf("a[0]= %p, a[0]+1 = %p \n",a[0],a[0]+1);//a[0]= 0060FE98, a[0]+1 = 0060FE9C 输出a[0]地址,a[0]+1的地址
printf("*a = %p, *a+1 = %d *(*a+1) = %d\n",*a,*a+1,*(*a+1));//a[0]= 0060FE98, a[0]+1 = 0060FE9C 输出的就是a的地址和a的地址+sizeof(int)
printf("a[0][0] = %d\n",a[0][0]);//输出a[0][0]元素的值
printf("*a[1] = %d *a[0]+1 = %d\n",*a[1], *a[0]+1);//*a[1] = 4 *a[0]+1 = 2 输出的是数组a[1]首元素 和a[0]首元素+1
printf("**a = %d\n", **a);//输出的是a[0][0]的值
printf("*(*a+2) +5= %d\n", *(*a+1)+5);//先把a指向第一行a[0]数组,然后访问a[0]数组的第二个元素2,再给2加上5
printf("a[1][2]= %d\n",a[1][2]);//输出a[1][2]的元素的值
printf("*(*(a+1))+4 = %d\n",*(*(a+1))+4);//输出的是a[1][1] + 4
printf("*(*(a+1)+2) = %d\n",*(*(a+1)+2));//输出的是a[1][2]上面的值*/
}
重点:
#include<stdio.h>
int main()
{
int(*p)[4][3] = NULL;//p是一个三维指针 0
printf("%d\n", *p);//0 *p 是一个二维指针 0
printf("%d\n",**p); //**p 降到一维
printf("%d\n",***p); //不会打印,***p是对一维指针取值,
//*在下面三行代码中表示的是升维操作
int a = 0;
int *p1 = &a;//一级指针
int **p2 = &p1;//二级指针
*************************************************************************
//&对指针变量来说永远是取值
//&对数组名相关的,有时是取地址,有时是升唯
*************************************************************************
//下面的代码中&的作用是进行升维操作,代码有误,重在理解升维的概念和&的不同的作用
----------------------------------------------------------------------------------
&a[0][0] == a[0];
&a[0] == a;
return 0;
}