【C语言】指针
指针
指针:指针是一个值为内存地址的变量(或数据对象)。
一、指针的声明
//示例 int *pi; //pi是指向int类型变量的指针 char *pc; // pi是指向char类型变量的指针 float *pf; // pi是指向float类型变量的指针
在定义时,以下几种写法效果相同
int *p = NULL; int* p = NULL; int * p = NULL;
注意,指针的值虽然是地址,指针本身也是有自己的地址和大小的。在计算机中,指针的大小为8字节,在stm32中,为4字节。
二、指针的赋值与解引用
int num=2; int *p; p=# printf("%d",*p);//结果输出为2
赋值要符合指针的定义,要向指针赋一个地址,如果定义时未赋值,形成野指针(野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的)。
野指针因为指向地址是不可预知的,所以有3种情况:第一种是指向不可访问(操作系统不允许访问的敏感地址,譬如内核空间)的地址,结果是触发段错误,这种算是最好的情况了;第二种是指向一个可用的、而且没什么特别意义的空间(譬如我们曾经使用过但是已经不用的栈空间或堆空间),这时候程序运行不会出错,也不会对当前程序造成损害,这种情况下会掩盖你的程序错误,让你以为程序没问题,其实是有问题的;第三种情况就是指向了一个可用的空间,而且这个空间其实在程序中正在被使用(譬如说是程序的一个变量x),那么野指针的解引用就会刚好修改这个变量x的值,导致这个变量莫名其妙的被改变,程序出现离奇的错误。一般最终都会导致程序崩溃,或者数据被损害。这种危害是最大的。
为避免出现野指针导致的错误,常规的做法是:
第一点:定义指针时,同时初始化为NULL
第二点:在指针解引用之前,先去判断这个指针是不是NULL
第三点:指针使用完之后,将其赋值为NULL
第四点:在指针使用之前,将其赋值绑定给一个可用地址空间
关于NULL
#ifdef _cplusplus // 定义这个符号就表示当前是C++环境 #define NULL 0 // 在C++中NULL就是0 #else #define NULL (void *)0 // 在C中NULL是强制类型转换为void *的0 #endif
三、指针的操作
int arr[5]={1,2,3,4,5};//数组名本身为一个指针
取址操作: &arr
自加自减,与整数相加减: arr++; arr--; arr+=2;
在本例中,指针与整数相加减时,它所指向的地址增加或减少整数个int的大小,如arr+=2储存ar[2]的地址
指针求差:相同类型指针之间可以相减,差值为整数个指针类型大小
四、指针与const
const int *p; //const修饰p指向的变量 int const *p; //const修饰p指向的变量 int * const p; //const修饰p指针 const int * const p; //const两者都修饰
使用const可以保护数组的数据不被修改,相比于#define,const的用法更加灵活
const int days[3]={20,13,5};
此后数组的元素不能被修改,否则会报错
如果函数这样定义,那这个函数将不能改变要传入的数组
void show_arr (const double *p,int n);