目录
const修饰普通变量
常量化,只读read-only,修饰普通变量
不能通过变量名直接修改,可以通过指针进行间接修改
const int a=777;
int *p=&a;
printf("%d\n",a);
*p+=5;
printf("%d\n",a);
const修饰指针
int const *p=&a; //const修饰指针指向的内容;指针指向的内容不能被修改,可以修改指针的指向
int a=777;
int const *p=&a; //const int *p = &a;
int b=999;
p=&b; //原指针指向a,修改指针指向b
printf("%d\n",*p);
int * const p=&a;//修饰指针的指向;指向不能改,可以修改指向的内容
const修饰指针的指向,修饰指针指向的内容
int const a=777;
int const * const p=&a;
void
应用场景:修饰指针、修饰函数中参数返回值,不能修饰一个变量
void *P=NULL; //void *表示任意类型的指针;后期使用时需要强制转换
void *p=NULL; //定义一个任意类型的指针
char a='q';
p=&a;
printf("%c\n",*(char *)p); //实际应用时,需要对p强制转换
// 取内容:*(char *)p
// 取地址:(char *)p
[2]大小端存储
小端:低地址存放低字节数据,高地址存放高字节数据(右边高字节)
(个人计算机属于小端存储)
大端:低地址存放高字节数据,高地址存放低字节数据(左边高字节
[3]二级指针
一级指针存放普通变量地址
二级指针存放一级指针的地址
格式:存储类型 数据类型 **指针变量名
int **p
int a=8; q==&p q &p都表示一级指针的地址
int *p=&a; *q==*&p==p==&a *q p &a都表示普通常量地址
int **q=&p; **q==*p==*&a==a **q *p a都表示常量里存储的内容
指针大小:8字节
【4】指针和数组
指针和一维数组
直接访问:直接通过数组名进行访问
int a[5]={5,6,7,8,9}; 一维数组名是数组首地址
di | a | a+1 | a+2 | a+3 | a+4 |
地址 | &a[0] | &a[1] | &a[2] | &a[3] | &a[4] |
5 | 6 | 7 | 8 | 9 | |
元素 | a[0] | a[1] | a[2] | a[3] | a[4] |
取值 | *a | *(a+1) | *(a+2) | *(a+3) | a+4 |
间接访问:通过指针进行访问
int a[5]={5,6,7,8,9};
int *p=a;
di | p | p+1 | p+2 | p+3 | p+4 |
地址 | &p[0] | &p[1] | &p[2] | &p[3] | &p[4] |
5 | 6 | 7 | 8 | 9 | |
元素 | p[0] | p[1] | p[2] | p[3] | p[4] |
取值 | *p | *(p+1) | *(p+2) | *(p+3) | p+4 |
a和p是否完全一样?不是,a是数组名,是地址常量,不能为左值;p是指针变量,可以被修改。
int a[5]={5,16,27,38,49};
int *p=a;
运算方法:*和++都是单目运算符,优先级相同,从右向左运算,右括号先算括号
*p++ :先算p++,由于++在后,对p加*取内容,然后p+1
*(p++):同上
*++p :先算++p先p+1修改指向,再*取地址里的内容
*(++p):同上
(*p)++:先算*p,再算++,下次执行值加1
++*p:算*p,再算++,值在这次就应用
练习
int x[5]={10,20,30};
int*px = x;
printf("%d,",++*px); //11
printf("%d\n",*px); //11
px = x;//{11,20,30}
printf("%d,",(*px)++); //11
printf("%d\n",*px); //12
px = x+1;//{12,20,30}
printf("%d,",*px++); //20
printf("%d\n",*px); //30
px = x+1;//{12,20,30}
printf("%d,",*++px); //30
printf("%d\n",*px); //30
补充
char a[33]="hello"; //在栈区空间开辟33字节,存储“hello”
char *p="hello"; //“hello”存储在常量区;P在栈区,存储字符串所在常量区的地址
//p 只能读取内容
char *p="hello";
char *q="hello"; //p q都指向常量区的首地址
char a1[33]={"hello"};
char a2[33]={"hello"};//在栈区空间内的不同位置开辟空间,分别存储hello
指针和二维数组
int a[2][3]={1,2,3,4,5,6};
数组名表示行地址,一行里面由多列,行大于列,像访问列,需要加*降级
// *a第一行第一列 // a第一行首地址
//*a+1第一行第二列 //a+1第二行首地址
//*(a+1)第二行第一列 //a[0]第一行第一列
//*(a+1)+1第二行第二列 //a[0]+1第一行第二列
*降级列 | *a | *a+1 | *a+2 | *(a+1) | *(a+1)+1 | *(a+1)+2 |
列 | a[0] 1行1列 | a[0]+1 | a[0]+1 | a[1] 2行1lie | a[1]+1 | a[1]+2 |
行 | a | a+1 | ||||
地址 | &a[0][0] | &a[0][1] | &a[0][2] | &a[1][0] | &a[1][1] | &a[1][2] |
1 | 2 | 3 | 4 | 5 | 6 | |
元素 | a[0][0] | a[0][1] | a[0][2] | a[1][0] | a[1][1] | a[1][2] |
取值 | *a[0] | *a[0]+1 | *a[0]+1 | *a[1] | *a[1]+1 | *a[1]+2 |
**a | *(*a+1) | *(*a+2) | **(a+1) | *(*(a+1)+1) | *(*(a+1)+2) |
间接访问
int a[2][3]={2,3,4,5,6,7};
int *p=a;
printf("%p %p\n",a,a+1);//p是普通的指针变量;
printf("%p %p\n",p,p+1);//普通的指针变量无法灵活访问数组