指针是一种类型和(int char double一样的),它是用来储存地址的,同时指针还指向了那片空间。这里就要和前面学习过的一个操作符有联系了,那就是取地址操作符(&)。
先来看一下指针长什么样子?,int a=10;int *p=&a(这个操作是吧a的地址放在p里面);这里的p就是指针变量,它的类型就是int *。
我们还要学习一个操作符是解引用操作符(*),
int main()
{
int a=100;
int *p=&a;
* pa=0;
}
我们这里运用解引用,这个代码的作用就是通过a的地址找到指针指向那片区域来改变a的内容。这样我们就多了一种间接改变a的方法。你们感觉指针会有大小吗?如果有会是多大?
指针是有大小的,但不是根据他的类型来判断大小的。取决于环境,x86的情况下是4个字节,x64的情况下是8个字节。但是指针的类型也不是一点用都没有用的,解引用的操作符可以访问几个字节就和指针类型有关。比如 char *的就只可以访问一个字节,int *可以访问4个字节。同时指针的类型决定了指针向前或者向走一步的距离有多大?
其中还有一种比较特殊的指针是void *(也叫泛型指针),它可以接受任何类型的指针,不可以直接进行指针的加减和解引用。但是可以间接的,比如先进行强制类型转换就可以指针加减和解引用。
其实变量也是可以被修饰的,这里我们介绍一下const ,作用是让变量不可以被修改。
int main()
{
int m=0;//m可以被修改
m=20;
const int n=0;//n不可以被修改
return 0;
}
如果修改了,就违背了语法会报错。const 修饰指针变量有两种方法:
1.const 在*的左边(const int *p),修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。但是指针本身可以改变。
2.const 在*的右边(int const *p),修饰的是指针变量本身,保证了指针变量的内容不可以改变,但是指向的内容可以改变,可以通过指针改变。
指针是可以进行运算的,我们前面就提到了指针的整数加减。还剩下指针-(减)指针,指针的关系运算。
指针的整数加减有什么用嘞?因为储存的空间是连续的所以我们可以加减来找到前后的元素地址来访问元素。
指针-指针:也就是两个地址相减,得到是两者之间的距离!
指针的关系运算:
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int* p = arr;//这里的arr表示数组首元素的地址=&arr[0]
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
while (p < arr + sz)//指针比较大小
{
printf("%d ", *p);
p++;
}
return 0;
}
这里我们在来介绍一下一个更特殊的指针,它就是野指针。野指针:野指针指向的位置不知道(随机的,不明白的)。如果使用野指针就会报错!!所以我们要避免使用野指针,那有什么措施呢?
1.指针一定要初始化 2.指针不要越界访问 3.指针指向了被释放的空间 4.如果不知道把指针指向哪空间那就指向NULL 它是一个标识符常量,值是0,地址也是0。但是这个地址不能被使用。
这里的-858993460就是越界指针访问出现的随机值。
这里就是指针指向了已经被释放的空间,所以就报错了。
int main()
{
int *p=NULL;//这里就是把p指针指向了空指针
return 0;
}
最后我们再提一个东西那就是assert(断言),使用它需要包含一个头文件include<assert.h>
它是一个表达式assert()如果括号里面是非零值程序正常运行,一旦返回值是零,程序就运行不下去了。