首页 > 其他分享 >关于函数调用的总结

关于函数调用的总结

时间:2022-11-14 19:32:47浏览次数:42  
标签:总结 lt 函数调用 char gdb 关于 NULL buf ptr


首先强调的是:


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(&lt);
        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(&lt);
(gdb) s
12 strftime(buffer,15,"%Y%m%d%H%M%S",ptr);
(gdb) s
13 return 1;
(gdb) p buffer
$1 =

(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(&lt);
        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(&lt);
(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(&lt);
        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(&lt);
        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)​

当调用函数返回一个数组名时-->我们不能这么做

​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(&lt);
     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(&lt);
        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 **.​

标签:总结,lt,函数调用,char,gdb,关于,NULL,buf,ptr
From: https://blog.51cto.com/u_15747257/5850070

相关文章