欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言指针问题及小知识总结

程序员文章站 2024-03-07 19:44:39
...

1、C语言指针:
指针是C语言最重要的概念之一,用于储存变量的地址。
&是取地址运算符,*是间接运算符。(C语言中:%p是输出地址的转换说明)。
“*号在定义变量时,表示类型是指针,如 int *p = NULL 表示这是一个叫p的指针; *号在运算时,表示取指针指向地址的内容。
首先要说的是:非堆分配的内存是不需要free的。
再说p=NULL;指针的变化是 p指向了一个地址为0的内存,这就提醒别人不要对这个指针进行解引用的操作。NULL其实就是0x0。p=NULL后,p指向0x0这个地址。此处的地址,你没有访问权限。
空指针指没有定位内存的指针,值为null(0),你使用new或者malloc申请了指针p,使用后delete或者free,你必须将指针值设置为null,否则,p将成为一个非法指针,后续代码如果使用到该指针有可能会造成系统崩溃(内存不可以读不可写),或者,破坏自身有效内存数据(释放后,又在申请作为别的用途,恰巧系统分配了同一块内存)
free(p)是只是将malloc申请的内存空间释放,在不改变free()函数的原型前提下是无法做到P=NULL的,P=NULL相当于空指针,不指向任何有效的对象。绝对不允许间接使用空指针,否则程序会得到毫无用处的结果或者全部是零的值,或者会突然停止。P=null,之后,p还是原来的类型的,不变的。比如说 我定义了一个整形变量 int a = 1; 同时定义了一个指针p指向这个变量a: int *p = &a;
但我用完这个变量和指针的时候我把指针所指向的内存空间释放掉:free(p);这个时候p所指向的内存空间里面的数据1被清空的,但是指针p里面仍然存有一个地址(原来指向a变量内存空间的地址),此时通常再要把指针p设置成空指针:P = NULL。我的问题来了:从free(p);这条语句到p = NULL;这条语句,指针p的状态发生了哪些变化,到底什么样的指针才叫空指针?是不是P = NULL;之后,p里面所存放的地址就为空了?是这样理解吗?此时p还有指向的数据类型吗?比如说p还是一个int *型的指针吗?
还有通常用if (p != NULL)来预防错误,就是说如果当指针p为空指针的时候,这个指针就最好不要用,要不然可能会发生内存泄露、空指针一场等错误,为什么呢?

    int *p = &a; 这样的指针不可用 free , free 只是针对 malloc, realloc 的内存进行释放。
    空指针是指指针指向地址0,如果是你分配的内存,并且使用 free 释放,然后把指针置成 0 ,只是为了不进行非法的引用。
    如
   

char* tmp = (char*)malloc(1024);
    free(tmp);
    tmp = 0;

在 free 后,如果后面再引用 tmp, 因为是个空指针,会导致进行崩溃。
如果不置为0,比如

char* tmp = (char*)malloc(1024);
free(tmp);
char* tmp2 = (char*)malloc(1024);
memset(tmp, 0, 1024);


这样,由于堆管理特性,很可能 memset(tmp, 0, 1024)写了 tmp2 指向的空间。
这样,释放完 tmp 后,再使用它,谓之野指针。
使用野指针会造成不可预期的后果,而使用空指针会造成比较确定的后果:崩溃。
所以 释放完后给指针赋成空,很大程度是避免以后错误地使用指针。
free(p)//报告系统,我要释放内存,系统就将该内存块标记为未使用,但不影响p的值
p = NULL//free被执行后,你需要将该指针标记为空,因为p指向的内存以被系统收回,不属于你的程序
这两个语句一般是在一起使用的
总结:为了避免野指针,定义指针的时候必须给指针初始化(以防指针空间的数据没有及时清空),用free§释放掉指针所指的内存空间后,必须立即同时把p赋值为NULL,避免后面程序指针P而导致意想不到的错误,甚至系统崩溃!”

指针部分参考自:https://blog.csdn.net/henu1710252658/article/details/83046649

2、a++a+=1a=a+1++a 的区别与效率问题

a++:a先创建自身的一个副本,然后a自增1,最后返回副本的值

a+=1: 事实上相当于++a

a=a+1: 虽然有点雷同于a+=1,但不同的是此时右值的a和1做相加操作,形成一个副本然后赋值给a,所以有额外操作

++a:将a自增1并返回a

鉴于a++和++a的差别,C++Primer建议用++a作为for循环的递增量效率问题:

1.在内建数据类型时

(即自增表示式的结果没有被使用,只是简单的用于递增操作),这时这两个表达式的效率是相同的。

2.在自定义数据类型时

(主要指有类的情况),由于++a可以返回对象的引用,而a++一定要是返回对象的值。可想而知引用的开销当然比直接对对象进行操作要效率高很多,节省很多开销。

前置++和后置++存在本质上的区别:

前置++ 不会产生临时对象

后置++ 在返回时有一个临时对象的创建

在前置++和后置++ 效果相同的时候,最好使用前置++

3、if(NULL != p)if( p!=NULL )C语言中有什么区别

没什么区别,防止敲击键盘是出错时,编译器是否能提示报错。

if(NULL != p) 如果写错写成if(NULL = p) 会报错

if( p!=NULL ) 如果写错写成if(p=NULL) 不会报错

一种编程小技巧,易于检查出错位置。