指针
指针的格式: 变量类型 * 变量名,指针变量只能存储地址,指针就一个作用,能够根据一个地址值,访问对应的内存空间
c
int a = 10;
int *p = &a; //等于(int *)p = &a;
*p = 20; //这里*只是表明它是一个指针类型
int **p2 = &p; //指向指针的指针,只要在对方的类型上加* 就可以了,p的类型是int *1
2
3
4
2
3
4
**指针都是8个字节,为什么要区分类型,是为了在赋值和取值的时候,在对应的内存区域,例 **
c
int s = 4;
char a = 1;
int *b = &a;
printf("s = %p,a = %p,b = %p,a = %d",&s,&a,&b,*b);
打印结果:
s = 0x7ffeeb428b78,a = 0x7ffeeb428b77,b = 0x7ffeeb428b68,a = 1025,
之所以a得到的是1025,是因为a取得是4个字节的值,
s的二进制 0000 0000 0000 0000 0000 0000 0000 0100,
a的二进制 0000 0001,
获取*b的值,是从a的地址开始,获取到4个字节的二进制位。a的值变成 0000 0000 0000 0000 0000 0100 0000 0001
100 0000 0001转换成十进制就是10251
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
指针和数组的关系
指针指向数组的第一位数,指针+1根据数组的类型加对应的字节数,比如:
c
int a[5] = {1,2,3};
int *p = &a;
printf("p ==%p, p+1 = %p, a = %p, p自己的地址 = %p",p,p+1,&a,&p); // 这里p+1对应的字节加四个字节,如果数组是char类型 p+1是加一个字节
p =0x7ffee8ea5b80, p+1 = 0x7ffee8ea5b84, a = 0x7ffee8ea5b80, p自己的地址 = 0x7ffee8ea5b60
*p = a, 相当于*p = a[0],数组的地址就是数组内第一位数据的地址
p + 1 相当于 &a[1], 取对应的值 *(p + 1)1
2
3
4
5
6
7
2
3
4
5
6
7
定义一个方法,传过去一个数组内地址的某位数的值
c
int main(){
int a[5] = {10,20,30,40,50};
void changeAry(int *ary);
changeAry(&a[1]);
return 0;
}
void changeAry(int *ary){
printf("%d\n",ary[2]); //打印结果是40
}
&a[1] 相当于 *(ary + 1)1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
指针跟字符串的关系
%S在遇到\0的时候就不再往下查询了
c
char c[] = "it"; //变量字符串,可修改
char *c1 = "it"; //常量字符串,不可修改
printf("%c ---",*c1);
打印结果 i
指针字符串指向的是字符串首字符的地址
输出整个字符串
printf("%s ---",c1); //为什么这里可以得到整个字符串,因为%s遇到\0的时候就不再往下查询了
char *c1 = "it\0s";
printf("%s ---",c1); // 这样的打印结果也是it1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 存储空间分布
- 常量区: 存放常量字符串
- 堆: 对象
- 栈:局部变量
指针字符串存在常量区,拥有缓存,相同的字符串,存储地址相同,如
c
char *c1 = "it";
char *c2 = "it";
printf("c1 = %p , c2 = %p",c1,c2);
打印结果:c1 = 0x10f0a0f80 , c2 = 0x10f0a0f80 // c1、c2首位字符地址相同1
2
3
4
2
3
4
使用数组的字符串
c
char c1[] = "it";
char c2[] = "it";
printf("c1 = %p , c2 = %p",c1,c2);
打印结果:c1 = 0x7ffee1bdab69 , c2 = 0x7ffee1bdab661
2
3
4
2
3
4
指向函数的指针
函数在加载的时候也会有内存地址,指针是专门保存并指向内存地址的,所以指针也可以指向函数
c
void: 指针变量P指向的函数没有返回值
(): 指针变量P指向的函数没有形参
void (*p) (); // (*p)是固定写法
p = test;
(*p)();
p(); // 这两种都可以调用test方法
void test(){
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 局部变量: 生 命周期,从定义的那一行开始到方法结束,如果不初始化没有固定的初始值
- 全局变量: 从定义的那一行到文件结尾,会被后面的函数共享,程序启动时分配存储空间,程序退出时才会被销毁,默认初始值是0