指针定义
个人感觉3步骤
int main()
{
int a = 10;
//定义指针的三步骤
//1 *与变量结合代表是一个指针变量 2 要保存谁的地址,将他的定义形式放在此处
//3 用*p替换掉定义的变量
//*p
int *p =&a;
//分析
//1与*结合代表这个一个指针变量
//2p是变量,p的类型是将变量p本身拖黑,剩下的类型就是指针变量的类型 int *
//3指针变量p用来保存什么类型数据的地址 ,将指针变量p和指针变量p最近的*一起拖黑,
//剩下什么类型就保存什么类型数据的地址
//p = &a;
return 0;
}
指针变量的使用
在使用时,对一个表达式取*,就会对表达式减一级*,如果对表达式取&,就会加一级*
不管什么类型的指针,指针变量的大小与编译器系统有关
int main()
{
char *p1;
short *p2;
int *p3;
int **p4;//p4也是一个指针变量 int **
printf("%d\n",sizeof(p1));
printf("%d\n", sizeof(p2));
printf("%d\n", sizeof(p3));
printf("%d\n", sizeof(p4));
return 0;
}
宽度
不同类型的指针变量,取指针指向的内容的宽度
指针的宽度 = sizeof(将指针变量与指针变量最近的*拖黑,剩下的类型)
宽度也叫做步长;
步长: 指针加1跨过多少个字节
char *p 1
short *p 2
int *p 4
Int **p sizeof(int *) 4
14 不同类型的指针变量,取指针指向的内容的宽度
指针的宽度 = sizeof(将指针变量与指针变量最近的*拖黑,剩下的类型)
宽度也叫做步长;
步长: 指针加1跨过多少个字节
char *p 1
short *p 2
int *p 4
Int **p sizeof(int *) 4
空指针
空指针的作用就是 如果使用玩指针讲指针赋值NULL,方便提醒下次使用时是否能用
int main()
{
int a;
//将指针的值赋值为0,0x0000000 = NULL
int *p = NULL;//给指针p的内容赋值为0
*p = 200;//err 因为p保存了0x0000的地址,这个地址是不可以使用的,非法
printf("%d\n",*p);
system("pause");
return 0;
}
野指针
野指针就是没有初始化的指针,指针的指向是随机的,不可以操作指针
指针p保存的地址一定是定义过的即向系统申请过的
/野指针
int main01()
{
//野指针就是没有初始化的指针,指针的指向是随机的,不可以 操作野指针
//int a = 0;
//指针p保存的地址一定是定义过的(向系统申请过的)
int *p;//野指针
*p = 200;
printf("%d\n",*p);
return 0;
}
万能指针void*
万能指针可以保存任意类型的地址但是访问时需要根据实际类型进行转换
//万能指针
int main()
{
//void b; 不可以定义void类型的变量,因为编译器不知道给变量分配多大的空间
//但是可以定义void *类型,因为指针都是4个字节
int a = 10;
short b = 10;
void *p = (void *)&a;//万能指针可以保存任意的地址
void *q = (void *)&b;
//printf("%d\n", *p);//err p是void*,不知道取几个字节的大小
printf("%d\n",* (int *)p);// *( (int *)地址)
system("pause");
return 0;
}
const修饰变量
const修饰变量时,不能通过直接更改变量来改变,要通过变量的地址来改变变量的值
const修饰谁,谁不能直接被改变,要通过地址来直接改变
int main()
{
int a = 10;
int b = 20;
//const修饰的是 * 还是变量p,
//这里修饰的是*
//const int *p = &a;//不能通过 *p,改p所指向空间的内容
//*p = 100; err 因为不能通过p改p所指向空间的内容
//const修饰的变量p
//p保存的地址不可以修改
//int * const p = &a;
//p = &b;err p本身的值不能被更改
const int *const p = &a;//p本身的指向不能改变,不能通过*p修改p
//向那块空间的内容
system("pause");
return 0;
}
多级指针
多级指针
定义多级指针保存数据的地址时,定义的指针的类型只需要比要保持的数据的类型多一级*
//多级指针
int main()
{
int a = 10;
//*p int a int *p
int *p = &a;
//*q int *p int **q
int **q = &p;
//如果*和&相遇,相抵消
// **q == *(*q) == *(p) == a
//**q == *(*q) == *(&a) == a
printf("%d\n", **q);
// *k int **q int ***k
int ***k = &q;
//*符号结合,代表这个k是一个指针变量
//k是一个变量
//k的类型,将变量k拖黑,剩下的类型
//k用来保存谁的地址 将变量k和k最近的*一起拖黑,剩下什么类型
//就保存什么类型数据的地址
int *******************g;
int ********************f = &g;
system("pause");
return 0;
}
指针结合数组
指针结合数组
指针加1,跨过一个步长
int *p;
步长 = sizeof(int)
要得到内存的数据,就该先得到数据的地址
*(地址) 得到的是地址里面的内容
int main()
{
//int a[10] = {1,2,3,4,5,6,7,8,9,10};
int a[10] = { 0 };
//a 数组名,首元素的地址
int *p = a;//指针p保存的是首元素的地址
for (int i=0;i<sizeof(a)/sizeof(a[0]);i++)
{
//printf("%d ",a[i]);
//printf("%d ", *(p+i));
*(p + i) = i;
}
for (int i = 0; i<sizeof(a) / sizeof(a[0]); i++)
{
printf("%d ",a[i]);
//printf("%d ", *(p+i));
//*(p + i) = i;
}
system("pause");
return 0;
}
指针运算
指针运算
两指针(类型一致)相减,得到的是中间跨过多少元素
两指针相加没有意义
int main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
//sizeof(int [10])
int *p = a;
//int *q = (int *)(&a + 1) - 1;
int *q = &a[9];
printf("%d\n",q-p);// p+9 == q
printf("%d\n",*(p+3));
//两指针相加没有意义
// printf("%d\n", p+q);err
system("pause");
return 0;
}
指针数组
指针数组
整型数组 是一个数组,数组的每一个元素是整型
指针数组 是一个数组,数组的每一个元素都是一个指针
int main()
{
int a = 10;
int b = 20;
int c = 30;
// int *p1 = &a int *p2 = &a int *p2 = &a
//需求: 数组中的每一个元素都是指针(地址)
int *num[3] = {&a,&b,&c};
//printf("%d\n",sizeof(num));
&a == num[0]
//for(int i=0;i<sizeof(num)/sizeof(num[0]);i++)
//{
// printf("%d\n",*num[i]);
//
//}
//定义一个指针用来保存数组num首元素的地址
// num == &num[0] = &(int *) == int **
//num[0]是int *类型,要保持int *类型的地址,需要比它多一级*
int **k = num;
for (int i = 0; i < sizeof(num) / sizeof(num[0]); i++)
{
printf("%d ",**(k+i));
}
system("pause");
return 0;
}