指针
1.指针变量和地址
1.1 取地址操作符(&)
#include <stdio.h>
int main()
{
int a=10;
//&a;取出a的地址
printf("%p\n",&a);
return 0;
}
&a
取出的是a所占4个字节中地址较小的字节的地址
1.2 指针变量和解引用操作符(*)
1.2.1 指针变量
我们通过取地址操作符取出一个地址,必须储存起来,那我们应该放在哪里呢?(指针变量中)
int a=10;
int *p=&a;//p就是指针变量,取出a的地址并储存在p中
指针变量也是一种变量,这种变量就是用来存放地址的
1.2.2 如何拆解指针类型
int a=10;
int *p=&a;
这里int*
中的*
是在说明p
是指针变量,而前面的int
是在说明p
指向的是整型类型的对象
1.2.3 解引用操作符
我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)指向的对象
#include <stdio.h>
int main()
{
int a=10;
int *p=&a;
*p=0;
return 0;
}
*p
就是通过p
中存放的地址,找到指向的空间,*p
其实就是变量a
。所以*p=0;
这个操作就是把a
改成0
1.3 指针变量的大小
- 32位平台下地址是32个
bit
位,指针变量大小是4个字节 - 64位平台下地址是64个
bit
位,指针变量大小是8个字节 - 注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。
2.指针变量类型的意义
2.1 指针的解引用
指针的类型决定了,对指针解引用的时候有多大的权限(一次能操作几个字节)
例如:char*
的指针解引用就只能访问一个字节,而int*
的指针的解引用就能访问4个字节
2.2 指针+ - 整数
我们可以看出,char*
类型的指针变量+1跳过一个字节,int*
类型的指针变量+1跳过了4个字节
结论:指针的类型决定了指针向前或者向后走一步有多大距离
2.3 void*指针
这种类型指针可以用来接受任意类型的地址。但是具有局限性,void*
类型的指针不能直接进行指针的+ - 整数和解引用的运算
一般void *
类型的指针是使用在函数参数的部分,用来接收不用类型数据的地址
3.const修饰指针
3.1 const 修饰变量
变量是可以修改的,如果我们在变量前面加上const
之后,该变量就不能被修改了
#include <stdio.h>
int main()
{
int m=0;
m=20;//m可以被修改
const int n=0;
n=20;//n不能被修改
return 0;
}
3.2 const修饰指针变量
一般来讲const
修饰指针变量,可以放在*
的左边,也可以放在*
的右边,意义是不一样的
int *p;//没有xonst 修饰
int const *p;//const 放在*的左边修饰
int *const p;//const 放在*的右边修饰
结论:
const
如果放在*
的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。但是指针变量本身的内容可以改变const
如果放在*
的右边,修饰的是指针变量本身,保证了指针变量的内容不能被修改,但是指针指向的内容,可以通过指针改变
4.指针运算
4.1 指针 + - 整数
因为数组在内存中是连续存放的,只要知道了第一个元素的地址,就能找到后面所有的元素
int arr[10]={1,2,3,4,5,6,7,8,9,10};
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int *p=&arr[0];
int i=0;
for(i=0;i<10;i++)
{
printf("%d ",*(p+i));
}
return 0;
}
4.2 指针 - 指针
#include <stdio.h>
int strlen1(char *s)
{
char *p=s;
while(*p!='\0')
{
p++;
}
return p-s;
}
int main()
{
printf("%d\n",strlen1("abcdef"));
return 0;
}
4.3 指针的关系运算
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int *p=arr;
while(p<arr+10){
printf("%d ",*p);
p++;
}
return 0;
}
5.野指针
就是指针指向的位置是不可知的
5.1 野指针成因
- 指针未初始化
- 指针越界访问
- 指针指向的空间释放
5.2 如何规避野指针
5.2.1 指针初始化
如果明确知道指针指向哪里就直接赋值地址,如果不知道,可以个指针赋值NULL
NULL
是C语言中定义的一个标识符常量,值是0,0也是地址,这个地址是无法使用的
int num=10;
int *p1=#
int *p2=NULL;
5.2.2 小心指针越界
一个程序申请了那些空间,通过指针也只能访问那些空间,不能超出访问的范围
6.数组名的理解
- 数组名就是数组首元素的地址
sizeof(数组名)
,sizeof
中单独放数组名,表示整个数组,计算的是整个数组的大小,单位是字节&数组名
,这里的数组名表示整个数组,取出的是整个数组的地址
7.使用指针访问数组
#include <stdio.h>
int main()
{
int arr[10]={0};
//输入
int i=0;
int *p=arr;
for(i=0;i<10;i++)
{
scanf("%d",p+i);
}
//输出
for(i=0;i<10;i++)
{
printf("%d ",*(p+i));
}
return 0;
}
8.二级指针
指针也是变量,是变量就有地址,指针变量的地址存放在二级指针中
二级指针跟一级指针用法类似