目录
一、指针修饰
const void
const 常量化 只读
const修饰普通变量
不能直接通过变量名修改,通过指针间接修改
const int a = 777; // int const a = 777;
int *p=&a;
1、a+=5; //报错
2、*p+=5;
printf("%d\n",a);
const修饰指针
1.int a=777;
int const *p=&a; //const修饰指针指向的内容; 指向的内容不能被修改,可以修改指针的指向
int a=777;
int const *p=&a; //const int *p = &a;
// *p=999; //错误
int b=999;
p=&b;
printf("%d\n",*p);
2.int a=777;
int * const p=&a; //const修饰指针的指向;指向不能改,可以修改指向的内容
int a=777;
int * const p=&a;
*p=999;
printf("%d\n",a);
3.const修饰指针的指向,修饰指针指向的内容
int const a = 777;
int const * const p = &a;
void
应用场景:
1).修饰指针
2).函数中的函数参数或返回值
3).不能修饰变量 void a; //错误
void *p=NULL; //定义一个任意类型的指针
char a='q';
p=&a;
printf("%c\n",*(char *)p); //实际应用时,需要对p强制转换
printf("%p\n",(char *)p);
//取地址:(char *)p
//取内容:*(char *)p
二、大小端
小端:低地址存放低字节数据,高地址存放高字节数据
大端:低地址存放高字节数据,高地址存放低字节数据
例: 0x12345678 //78为低字节高地址,12相反
大端:12 34 56 78
小端:78 56 34 12
三、二级指针
一级指针存放普通变量的地址
二级指针存放一级指针的地址
格式:
存储类型 数据类型 **指针变量名
int **p;
int a = 8;
int *p = &a;
int **q = &p;
普通变量a的地址:*q p &a
普通变量a的值: **q *p a
一级指针的地址: q &p
q==&p q &p
*q==*&p==p=&a *q p &a
**q==*p==*&a==a **q *pa
四、指针和数组
指针和一维数组
直接访问:通过数组名
间接访问:通过指针
直接访问
int a[5]={5,6,7,8,9};
地址 | 元素 | |||
a | &a[0] | 5 | a[0] | *a |
a+1 | &a[1] | 6 | a[1] | *(a+1) |
a+2 | &a[2] | 7 | a[2] | *(a+2) |
a+3 | &a[3] | 8 | a[3] | *(a+3) |
a+4 | &a[4] | 9 | a[4] | *(a+4) |
间接访问
地址 | 元素 | |||
p | &a[0] | 5 | a[0] | *p |
p+1 | &a[1] | 6 | a[1] | *(p+1) |
p+2 | &a[2] | 7 | a[2] | *(p+2) |
p+3 | &a[3] | 8 | a[3] | *(p+3) |
p+4 | &a[4] | 9 | a[4] | *(p+4) |
a和p是否完全一样?
不是。a是数组名,是地址常量,不能是左值;
p是指针变量,可以被修改;
在输出或者赋值语句中:
*p++:先算p++,由于++在后,所以直接对p加*取内容,然后p+1
*(p++):同上
*++p:先++p,先p+1修改了指向,然后再加*取内容
*(++p):同上
(*p)++:先对p加*取内容,然后对当前内容++
++*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";
if(p==q)
printf("qqq\n"); //p q 都指向常量区的首地址
==============================
char a1[33]="hello";
char a2[33]="hello";
if(a1==a2)
printf("aaa\n"); //在栈区开辟了两个空间,只是两个空间中的内容正要相同。
指针和二维数组
int a[2][3] = {2,3,4,5,6,7};
//数组名是行地址,一行里边有多列,行>列,如果想访问到列,需要加*降级处理
//*a第一行第一列
//*a+1第一行第二列
//*(a+1)第二行第一列
//*(a+1)+1第二行第二列
// a第一行首地址
//a+1第二行首地址
//a[0]第一行第一列
//a[0]+1第一行第二列
地址 | 元素 | ||||||
*a | a[0] | a | &a[0][0] | 2 | a[0][0] | *a[0] | **a |
*a+1 | a[0]+1 | &a[0][1] | 3 | a[0][1] | *(a[0]+1) | *(*a+1) | |
*a+2 | a[0]+2 | &a[0][2] | 4 | a[0][2] | *(a[0]+2) | *(*a+2) | |
*(a+1) | a[1] | a+1 | &a[1][0] | 5 | a[1][0] | *a[1] | **(a+1) |
*(a+1)+1 | a[1]+1 | &a[1][1] | 6 | a[1][1] | *(a[1]+1) | *(*(a+1)+1) | |
*(a+1)+2 | a[1]+2 | &a[1][2] | 7 | a[1][2] | *(a[1]+2) | *(*(a+1)+2) |
int a[2][3]={2,3,4,5,6,7};
printf("%p %p\n",a,a+1);
printf("%p %p\n",*a,*a+1);
printf("%p\n",a+1);
printf("%p %p\n",*(a+1),*(a+1)+1);
间接访问
i
nt a[2][3]={2,3,4,5,6,7};
int *p=a;
printf("%p %p\n",a,a+1);
printf("%p %p\n",p,p+1);
//p是普通的指针变量;普通的指针变量无法灵活访问数组