指针变量:用来存放地址的变量。
这里讲一下为什么两位为一个字节:首先这是一个十六进制的地址,再十六进制中的F(15)用二进制表示是需要四位(1111),所以一位代表四个bit,两位则代表八个bit(即一个字节)。
编译器中的32位和64位代表的各位的比特位,一个字节八个bit,分别除以八得到:32位等价于四个字节,64位等价于八个字节。一个指针变量大小即是一个地址的大小(32位四个字节,64位八个字节)。
指针类型:变量有什么类型指针也有什么类型。下面简单讲几个类型,其他的同样道理:
- char* 类型的指针是为了存放 char 类型变量的地址。如果类型不一样的,需要进行类型转换。
- short* 类型的指针是为了存放 short 类型变量的地址。
- int* 类型的指针是为了存放 int 类型变量的地址。
指针的解引用:*是将指针变量(pa)解引用通过地址找到相应变量(a)改变其值。
野指针
- 指针未初始化。指针变量不初始化编译器会报错误(使用未初始化的局部变量),就像指针p没有地址,无法通过解引用找到地址。
- 指针越界访问 。 指针变量越界和变量越界道理一样。
- 指针指向的空间释放 。意思就是指针变量通过地址找变量时,地址销毁(不存在),也会出现野指针。(其中打印的结果符合预期是因为该块栈帧还未被占领,导致打印的结果与预期一致)
避免野指针
- 指针初始化:安全起见,使用指针前都进行初始化更好一些,可以使用空指针(NULL)。
- 小心指针越界
- 指针指向空间释放即使置NULL
- 避免返回局部变量的地址
- 指针使用之前检查有效性
指针运算
- 指针+整数:指针的类型不一样加同样一个整数结果不同,取决于指针类型。举例表示吧:
- 指针-指针:前提条件是在同一块空间里,绝对值的结果是两个指针之前的元素个数。也可以用于求字符个数。
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与 指向第一个元素之前的那个内存位置的指针进行比较。
数组和指针
数组名表示的是数组首元素的地址(例*p = arr)。可以通过首元素地址找数组的所有元素(arr[i]==*(arr+i))。
int main()
{
int arr[10] = { 0 };
int* p = arr;//不需要取地址符
int i = 0;
for (i = 0; i < 10; i++)
{
*p = (i + 1);
p++;
}
//for (i = 0; i < 10; i++)
//{
// printf("%d ", arr[i]);
//}
p = arr;
for (i = 0; i < 10; i++)
{
printf("%d ", *(p+i));
}
return 0;
}
二级指针:指针变量也是变量也是有地址的,这是就有了二级指针的概念。
指针数组:存放指针的数组。