首先强调的是:
C语言中所有函数调用都是传值调用
(数组是例外情况。C里数组名就表示了数组的首地址当把数组名当参数传递时,其实也就是传了个地址而已)
1、传值调用时是copy一份传给函数,在函数体内对传给函数的变量做修改不会影响原变量。这种方法如果传的对象比较大会增加很多的内存开销。
#include <stdio.h> void *fun(char *a) { a="zerk"; return; } int main(void) { char *s=NULL; printf("----------/n"); fun(s); printf("%s/n",s); } 输出: ./a.out ---------- (null)
|
2、传引用调用实际上是把变量的地址传给函数,所以程序的效率比较高。如果你想返回对变量的修改值,必须用“指向指针”的指针做为函数的参数。
#include <stdio.h> void *fun(char **a) { *a="zerk"; return; } int main(void) { char *s=NULL; printf("----------/n"); fun(&s); printf("%s/n",s); }
输出: ./a.out ---------- zerk
|
下面通过对一个取得当前时间的函数的实现的改造过程来说明:
1 实参:一级指针 形参:一级指针 返回类型:int
#include <stdio.h> #include <time.h> int get_datetime( char * buffer ) { struct tm * ptr = NULL ; time_t lt = 0 ;
lt =time(NULL); ptr = localtime(<); strftime(buffer,15,"%Y%m%d%H%M%S",ptr); return 1; } int main(void) {
char *buf=NULL; get_datetime(buf); printf("[%s]/n",buf); }
输出: ./a.out [(null)]
|
gdb调试:
Breakpoint 1, main () at time.c:19 19 char *buf=NULL; (gdb) s 20 get_datetime(buf); (gdb) s get_datetime (buffer=0x0) at time.c:7 7 struct tm * ptr = NULL ; (gdb) s 8 time_t lt = 0 ; (gdb) s 10 lt =time(NULL); (gdb) s 11 ptr = localtime(<); (gdb) s 12 strftime(buffer,15,"%Y%m%d%H%M%S",ptr); (gdb) s 13 return 1; (gdb) p buffer $1 = 0x0 (gdb) s 14 } (gdb) s main () at time.c:21 21 printf("[%s]/n",buf); (gdb) s [(null)]
|
2 实参:数组 形参:数组名 返回:int-->验证了数组这一特殊情况
#include <stdio.h> #include <time.h>
int get_datetime( char * buffer ) { struct tm * ptr = NULL ; time_t lt = 0 ;
lt =time(NULL); ptr = localtime(<); strftime(buffer,15,"%Y%m%d%H%M%S",ptr); return 1; }
int main(void) {
char buf[15]={0}; get_datetime(buf); printf("[%s]/n",buf); }
输出:/a.out [20071018105321]
|
gdb调试:
Breakpoint 1, main () at time.c:19 19 char buf[15]={0}; (gdb) s 20 get_datetime(buf); (gdb) s get_datetime (buffer=0xbfffe470 "") at time.c:7 7 struct tm * ptr = NULL ; (gdb) s 8 time_t lt = 0 ; (gdb) s 10 lt =time(NULL); (gdb) s 11 ptr = localtime(<); (gdb) s 12 strftime(buffer,15,"%Y%m%d%H%M%S",ptr); (gdb) s 13 return 1; (gdb) p buffer $1 = 0xbfffe470 "20071018105524" (gdb) s 14 } (gdb) p buf $2 = 0 (gdb) s main () at time.c:21 21 printf("[%s]/n",buf); (gdb) p buf $3 = "20071018105524" (gdb) s [20071018105524] 22 }
|
3、调用函数无形参,返回char*型
#include <stdio.h> #include <time.h> char * get_datetime( void ) { char *buffer=NULL; buffer=(char *)malloc(sizeof(char)*15); struct tm * ptr = NULL ; time_t lt = 0 ;
lt =time(NULL); ptr = localtime(<); strftime(buffer,15,"%Y%m%d%H%M%S",ptr); return buffer; } int main(void) {
char *buf=NULL; buf=get_datetime(); printf("[%s]/n",buf); free(buf); } 输出:./a.out [20071018112403]
|
容易犯的错误:
#include <stdio.h> #include <time.h> char * get_datetime( void ) { char *buffer=NULL;//buffer为局部变量,调用函数结束后自动释放 // buffer=(char *)malloc(sizeof(char)*15);//函数调用结束后虽然Buffer释放了,但它分配的那块内存依然有效。 struct tm * ptr = NULL ; time_t lt = 0 ;
lt =time(NULL); ptr = localtime(<); strftime(buffer,15,"%Y%m%d%H%M%S",ptr); return buffer; }
int main(void) {
char *buf=NULL; buf=get_datetime(); printf("[%s]/n",buf); // free(buf); } 输出:./a.out (NULL)
|
当调用函数返回一个数组名时-->我们不能这么做
1 #include <stdio.h> 2 #include <time.h>
3 4 5 char * get_datetime( void ) 6 { 7 char buffer[15]={0}; 8 struct tm * ptr = NULL ; 9 time_t lt = 0 ; 10 11 lt =time(NULL); 12 ptr = localtime(<); 13 strftime(buffer,15,"%Y%m%d%H%M%S",ptr); 14 return buffer; 15 } 16 17 int main(void) 18 { 19 20 char *buf=NULL; 21 buf=get_datetime(); 22 printf("[%s]/n",buf); 23 }
输出:./a.out [囵B B橍縐?卲?繕?緽? Bp?扛?縯UB]
|
4、形参实参为二级指针:
#include <stdio.h> #include <time.h>
void get_datetime( char **buffer )//这是一般性的作法 { char *tmp=NULL; tmp=(char*)malloc(sizeof(char)*15); struct tm * ptr = NULL ; time_t lt = 0 ;
lt =time(NULL); ptr = localtime(<); strftime(tmp,15,"%Y%m%d%H%M%S",ptr); *buffer=tmp; return ; }
int main(void) { char *buf=NULL; get_datetime(&buf); printf("[%s]/n",buf); }
输出:./a.out [20071018121352]
|
cu的scutan有些话值得思考一番:
void fun(int i) { i = i + 10; }
int i = 10; fun(i); 这种情况下调用了fun之后i的值会变吗?
同样:
void fun(char *p) { p = ...; }
char *p; fun(p);
这种情况下, 当然也不会变了啊.
而你可能经常看到的用法是 char c; fun(&c); 此时传递的是c的地址, 而后面是对这个地址进行操作,
所以说**p,就是针对的改变char *p这种类型的值, 因为传递给这个参数的是一个指针的地址 其实你要传递给函数的不过是一个地址罢了. 通过这个地址修改这个值. 所以: 对于 char c, 指向一个字符类型的指针为char *p; 所以函数参数为这个. 对于 char *p, 指向一个字符类型指针的指针为char **p, 所以函数参数为char **p,而此时则需要将p的地址传递给这个函数作为参数,所以就是&p. 其实看开了, char , char *, 都是类型, 不要因为有个什么*号就迷糊了. 需要指向它们的指针, 就相应地加上*号成为 char *, char **.
|
分享到:
相关推荐
自动生成c++函数调用关系图,里面包含了所有要用到的软件,一站式服务; 通过本人亲测的使用总结; 还有使用到的配置文件(c++的),实在不会配置可以直接使用; 改一改配置文件,应该还可以生成c,java,c#语言的调用...
自己总结了一点C,C++的资料,主要讲空类中的默认函数, 以及函数调用时栈的调用关系.
C语言是一个强大的语言,特别是对于嵌入式开发过程中有时需要反汇编分析代码中存在的问题,函数是C语言中的难点,关于函数的调用也是很多人不能理解的,很多知道的也是一知半解。对C语言的调用有了一个比较清晰的...
python实验报告-函数定义和调用
1.掌握C语言函数的定义、声明以及函数的调用方法2.了解主调函数和被调函数之间的参数传递方式3.熟练掌握数组作为函数参数的用法
函数调用,参数堆栈等学习资料...关于函数调用时堆栈的变化分析(转自Jim's blog) - H_S_的学习总结与心得 - 博客园.mht 函数参数堆栈.txt 函数调用堆栈分析.doc 转贴:关于函数调用的深入分析 百度空间_应用平台.mht
这是我自己总结的关于MATLAB各类函数的调用说明,其中包括图像处理方面的,画图显示的以及数值分析等
MATLAB中函数调用格式总结更具实用性共22页.doc
NULL 博文链接:https://zhangxing119.iteye.com/blog/846867
本文实例讲述了Python实现调用另一个路径下py文件中的函数方法。分享给大家供大家参考,具体如下: 针对这个问题,网上有很多的解决方式。其实最主要的原因是因为Python无法正确找到你其他文件夹下文件的路径。针对...
1.构造函数调用 常用初始化列表 或者显示调用 1.1同一个类中构造函数调用构造函数 尽量不要这样做,因为结果不确定!避免麻烦 可以把共用的代码封装成一个私有的成员函数,然后在构造函数内统一调用。 1.2子类...
用同一个类的源对象构造一个目标对象时,会调用拷贝构造函数来构造目标对象,如果没有定义拷贝构造函数,将调用类的默认拷贝函数来构造目标对象。2 . 当一个函数的返回值为一个类的对象时,如果在调用函数中,没有...
本篇文章主要是对C/C++函数调用的几种方式进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
” rel=”external nofollow” rel=”external nofollow” rel=”external nofollow” ,其中[removed]是伪协议,它可以让我们通过一个链接来调用javascript函数.而采用这个方式 [removed];可以实现A标签的点击事件...
前台js与后台C#互相调用 这里总结的很好,拿来了,另外加了点说明 C#代码与javaScript函数的相互调用
假如函数在调用它之前定义... 您可能感兴趣的文章:深入理解C++中public、protected及private用法C/C++函数调用的几种方式总结浅析C语言中堆和栈的区别关于C语言中参数的传值问题浅谈C语言函数调用参数压栈的相关问题
VS2005如何调用Matlab7定义的.m文件中的函数[总结].pdf
重载虚函数:Unity3D中所有控制脚本的基类MonoBehaviour有一些虚函数用于绘制中事件的回调,也可以直接理解为事件函数,例如大家都很清楚的Start