开始学习前,先说明一下,下述所写代码均是伪代码哦。
int n;
&n;//通过取地址符&可以得到n的地址
int *p=NULL://初始化指针变量p
//----------------------------
int a=10;
int *p=&a;//用指针变量p存放a的地址
printf("%d",*p);//p中存放的是a的地址,*p解引用得到a中的数据,即*p=10;
//值得补充的是,解引用可以修改指针指向的地址的内容,如上述可以*p=0,a的值也就为0了,可以运用在跨
//函数修改值的情况下
int a=10;
int *p=&a;//用指针变量p存放a的地址
*p=0;
printf("%d",a);//p中存放的是a的地址,*p解引用修改了a中的数据,即a==*p==0;
//-----------------------------------------
void test(int *p) //跨函数的情况下
{
*p=0;//*p将a中的值修改为0
}
int main()
{
int a=10;
test(&a);
printf("%d",a);//此时a==0;
无论什么类型的指针,如char *p;int *p;double *p。这些指针的大小但是相同的,在32位的操作系统下是4个字节的大小,在64位的操作系统下是8个字节的大小。
(1)解引用时不同
int n=0x11223344;
int *pa=&n;
*pa=0;
printf("%x",n);//n=0x00000000;
//--------------------------
int n=0x11223344;
char *pb=&n;
*pb=0;
printf("%x",n);//n=0x00223344;
(2)加减时不同
int n=10;//假设n的地址是0x00000001
int *pa=&n;
char *pb=&n;
printf("%p",&n);//&n=0x00000001;
printf("%p",pb+1);//pb+1=00000002;//指针类型决定了加减的大小,如char*加减1位,int*加减4位
printf("%p",pa+1);//pa+1=00000005;
(3)特殊指针类型(void*)
void*指针类型不能进行加减运算,也不能进行解引用运算,void*的指针该如何使用呢?
⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以 实现泛型编程的效果。使得⼀个函数来处理多种类型的数据。处理时用强制类型转换即可。日后遇见就明白了。
const说白了就是保持数据不变的作用。
//-----------------------------------------------
//第一种情况,const在*前
int n=0;
int *p=&n;
*p=10;//ture
printf("%d",n);//n被修改为10
int n=0;
const int *p=&n;
*p=10;//error,此时会报错,const修饰后,解引用只能是n=0,不能再修改
printf("%d",n);p
//-----------------------------------------------
//第二种情况,const在*后
int m=0;
int n=0;
int *p=&m;
p=&n;//ture
printf("%p",&m);
printf("%p",&n);
printf("%p",p);//p指向的是n的地址
int m=0;
int n=0;
int * const p=&m;
p=&n;//error,此时会报错,const修饰后,p只能指向m的地址,不能再指向其它的地址
printf("%p",&m);
printf("%p",&n);
printf("%p",p);
//-----------------------------------------------
//第三种情况,const既在*前,也在*后
//也就是前两种情况的结合,不能解引用修改值,也不能改变指向的地址,这里不再赘述。
//-----------------------------------------------
//补充不是指针的情况下
int n=0;
n=10;//ture
const int n=0;
n=10;//error,此时会报错,const修饰后,变量也不可更改
(1)加减运算:就是根据指针类型加减不同的大小,前面讲过,这里不再赘述。
(2)指针-指针:就是指针之间元素数目的差值,如是int*指针相减等于字节数/4,char*指针相减等于字节数/1,不同类型的指针不能相减,必须是相同类型的指针。
(3)指针大小的判断:&a=0x00000001,&b=0x00000002,&a<&b,根据指针指向的地址大小来判断。
(1)局部指针未初始化,默认为随机值。如:
#include
int main()
{
int *p;//局部变量指针未初始化,默认为随机值,应当int *p=NULL;
*p = 20;
return 0;
}
(2)越界访问
int a[10]={0};
int *p=a[10];//数组a只有a[0]到a[9],此时越界了
(3)指针指向的地址被释放
void stm()
{
int a=10;
return &a;
}
int main()
{
int *p=stm();//a是局部变量,在stm()函数结束时已经被销毁了,&a已经不存在了
return 0;
}
(1)初始化时给确切的地址或赋NULL
int *p=NULL;
//或者
int a=10;
int*p=&a;
(2)避免越界访问
(3)避免接受返回的局部变量的地址
(4)当用完指针时,习惯将指针置NULL,习惯使用指针时检查指针的有效性。
assert(表达式),若表达式为假,系统会报错。常用于判断指针是否非空。若不需要,只需加宏定义#define NDEBUG即可,系统默认assert语句无效。所需头文件为assert.h。缺点就是多了代码,就多耗费时间。
博主本人也是菜鸟,这些是我学习后总结出来的知识点,希望可以帮到大家,大家互相学习,共同进步。欢迎大家指出错误。