原创声明:近期发现在关键字搜索我的文章时,发现很多文章被其他网站直接一字不落的拿去。在这里我先谢谢大家对我写的内容的肯定,我也会继续努力。但是,很多网站连标明都未标明来源,这就让人很可气,毕竟每一篇文章都是我一个字一个字敲出来的。我也不是在抱怨什么,只是希望那些某些站长在“转载”他人文章时标明来源,注明作者。不要只是简单的一个来源互联网。万分感谢。
此外,本站文章如未标注文章来源,则均为作者原创,请转载附上原文链接,并声明作者。保护原创,从我做起,谢谢合作。
如果是我的项目的话,源码会全部上传到我的Github,大家有需要的可以拿去研究,也可以我们一起交流探讨。最后,祝愿每一个默默努力的人都可以取得理想的结果。
-----------吃土少年8
首先要声明c语言是没有引用传参的哈,引用传参是c++的语法。但是如果我们也想实现一样的效果该怎么写呢?(函数内的值变化可以直接对原参数的值进行更改)
其实原理都是一样的,我们细想c++的引用传参,其实就是把参数的地址作为参数传进了函数体内。函数体内的操作都是基于该地址上的参数进行变化的,而不是将参数的值进行拷贝传进函数体内。
同样,c语言也可以实现上述效果。我们怎么做呢?也是传地址,传地址,再对该地址上的值进行变化即可。代码如下:
void add(int *s){ // 这个*s是其实要的是一个地址,因为指针本身就是地址 int a=199; *s=a; // 这里的*s是在将s这个地址上的值进行变化 } int main(){ int s=1; //实参s printf("变化前地址:%d\n",&s); printf("变化前:%d\n",s); add(&s); printf("变化后地址:%d\n",&s); printf("变化后:%d\n",s); return 0; }结果如下:
变化前地址:6422044 变化前:1 变化后地址:6422044 变化后:199当然,我们s也可以定义成指针,同样也是传地址,现在要传的是指针的地址,并且一定记得要给指针分配内存,要不然会有段错误(Segmentation fault)!!!!代码如下:
void add(int *s){ // 这个*s是是一个指针 int a=321; *s=a; // 这里就是这一步就是把a的值给指针s } int main(){ int *q; //实参p q=(int *)malloc(sizeof(int)); printf("变化前地址:%d\n",&q); printf("变化前:%d\n",*q); add(q); printf("变化后地址:%d\n",&q); printf("变化后:%d\n",*q); return 0; }结果如下:
变化前地址:6422040 变化前:-1163005939 变化后地址:6422040 变化后:321这里我们也可以练一下二级指针,加深一下理解,代码如下:
int a=321; void add(int **s){ // 这个**s是其实是一个二级指针 *s=&a; // 这里就是将a的地址让*s存起来,传递的是址 } int main(){ int **p; //实参p p=(int *)malloc(sizeof(int)); int x=123; *p=&x; // 这里要定义一个x,让*p存x的址,否则会段错误 printf("变化前地址:%d\n",&p); printf("变化前:%d\n",**p); add(p); printf("变化后地址:%d\n",&p); printf("变化后:%d\n",**p); return 0; }结果如下:
变化前地址:6422040 变化前:123 变化后地址:6422040 变化后:321可能你会好奇,为啥这里要用二级指针?为啥a要定义成全局变量?
用二级指针是因为我们要在函数体内对指针进行变化,且函数运行结束后,对指针的更改仍然有效。
这里为什么不是和刚才一样定义成局部变量是因为涉及到c的内存分配,我们这里是传址。局部变量是开辟在栈内存中的,局部变量的址和值在函数体内有效,出了函数体就销毁了,也就是看起来为啥用了二级指针还是改不了?因为是局部的。所以我们改成全局的,放在堆内存中,这样就实现了我们对指针进行变化的想法。
段错误处理:
出现段错误时,首先应该想到段错误的定义,从 它出发考虑引发错误的原因。在使用指针时,定乂了指针后记得初始化指针, 在使用的时候记得判断是否为NULL。在使用数组时,注意数组是否被初始化,数组下 标是否越界,数组元素是否存在等。在访问变量时,注意变量所占地址空间是否已经 被程序释放掉。在处理变量时,注意变量的格式控制是否合理 等