前言:
作为自己复习用。
1.指针
指针就是地址,指针用来存储其他一般变量的地址。
int a = 112, b = -1;
float c = 3.14;
int* d = &a;
float* e = &c;
这里定义了五个变量,每个变量都进行了初始化,我们分别都给他们地址假定可以如下图表示:
指针的初始化是由&操作符完成的,用于获取变量的内存地址,也就是说我们将a、c的内存地址分别用指针变量d、e保存起来。
因此对于d来说它的内容是a的地址,e的内容是c的地址,这里注意要与d、e本身的地址区别开!
d = 100; //a的地址
e = 108; //c的地址
*d = 112;
*e = 3.14;
2.指针的初始化和野指针
int* a;
*a = 12;
这种写法是错误的,并没有初始化a,这时,a就是野指针。
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
这种未初始化的指针就是野指针的一种。
此外指针对数组进行越界访问也是。
这里做一个小的总结,如何规避野指针:
- 1. 指针初始化
- 2. 小心指针越界
- 3. 指针指向空间释放即使置NULL
- 4. 避免返回局部变量的地址
- 5. 指针使用之前检查有效性
3.const和指针
无非三种结合形式:
const int* p;
int* const p;
const int* const p;
第一种const int* p.
这里的const对指针进行了限定,就不能改变指针的值,也就是对p进行解引用的值不能改变,但可以改变其地址。
第二种int* const p.
这里的const对p进行限定,就不能改变p的内容
p的指向为100这个内存空间,不能再被更改。
第三种无非是对前两种的集合,p的指向以及对其解引用所得的值都不可改变。
4.指针数组与数组指针
int* parr[3];//指针数组
int(* pbrr) [3];//数组指针
这里的不同之处就在于*和[]运算符的优先级不同,[]的优先级高于*,用图片更容易理解
int* parr[5];
int brr[5] = { 1,2,3,4,5 };
int(*pbrr)[5] = &brr;
printf("int* parr[5] = %d", sizeof(parr));
printf("int(*pbrr)[5] = %d", sizeof(pbrr));
指针数组parr的大小为整个数组的指针大小的和
数组指针pbrr的大小为指针的大小
5.指针加减法
5.1指针加减整数
对指针进行加减就是加减其对应的类型的字节数。
int main()
{
char ch = 'a';
int i = 0;
char* p1 = &ch;
int* p2 = &i;
printf("p1 = %p\n", p1);
printf("p1 + 1 = %p\n", p1 + 1);
printf("p2 = %p\n", p2);
printf("p2 + 1 = %p\n", p2 + 1);
return 0;
}
对char*类型加一就是增加1个字节,对int*类型加一就是增加4个字节。
5.2指针减指针
//指针减指针
int main()
{
int arr[5] = { 1,2,3,4,5 };
int* pa = &arr[0];
int* pb = &arr[4];
printf("%d", pb - pa);
return 0;
}
指针减指针就是两者所对应的地址相减除以再除以其类型。
如果以上的pa、pb为char*型,那么其结果就为16.