C语言中函数返回字符串的4中方法

  • 函数的构成部分:返回类型、函数名称、参数、函数主体
  • 参数:函数调用时传入的参数称为实参,函数定义时出现的参数为形参
    • 形参的作用在于接收实参传入的值,形参和函数内部的其他局部变量相同,在进入函数创建,退出函数销毁
    • 值传递:实参的实际值复制给形式参数。修改形参不会改变实际参数
    • 引用传递:指针传递,将实参地址复制给形参,修改形参指向的值时,实参也会发生改变
    • 由此,可以得知无论是形式结合还是return语句返回时,都存在一个拷贝的过程。值传递的过程是将这个值拷贝一份在函数内部使用,引用传递的过程是将地址拷贝一份使用。同样在return返回时,返回一个值,函数会将该值拷贝一份供主函数使用,返回指针,自然拷贝的就是一个地址,供主函数使用。
  • 下面是一个错误示例
  •   #include <stdio.h>
    #include <string.h> char * retstring();
    int main()
    {
    char * name2;
    name2 = retstring();
    printf("%s\n",name2);
    return 0;
    } char * retstring()
    {
    char name[10];
    strcpy(name,"汉青");
    return name;
    }
  • 上面这段代码会出现一个警告,这是因为返回了一个局部变量name的地址。在主函数中该局部变量name时处于销毁状态,所以name内存空间还没有被重写的话主函数中name2的值是正确,如果被其他程序重写,就会出现未知异常。
  • 所以返回局部变量的字符串时很可怕的
  • 函数返回字符串的方法:
    1. 将字符串指针作为函数参数传入,并返回该指针
    2. 使用malloc函数动态分配内存,在主调函数中释放
    3. 返回一个静态局部变量
    4. 使用全局变量

将字符串指针作为函数参数传入,并返回

  • 典型的strcpy函数应该采用的就是这种方法:

    •   char* strcpy(char* des,const char* source)
      {
      char* r=des;
      assert((des != NULL) && (source != NULL));
      while((*r++ = *source++)!='\0');
      return des;
      }

使用malloc函数动态分配内存,但是一定要注意在主调函数中将其释放,因为malloc动态分配的内存位于堆区,而堆区的内存是需要自己释放的###

  •   #include <stdio.h>
    #include <string.h>
    #include <stdlib.h> char * retstring();
    int main()
    {
    char * name2;
    name2 = retstring();
    printf("%s\n",name2);
    //记住一定要用free释放,否则会造成内存泄露
    free(name2);
    return 0;
    } char * retstring()
    {
    char * name;
    name = (char *)malloc(10);
    strcpy(name,"张汉青");
    return name;
    }

返回一个静态局部变量

  •   #include <stdio.h>
    #include <string.h>
    #include <stdlib.h> char * retstring();
    int main()
    {
    char * name2;
    name2 = retstring();
    printf("%s\n",name2);
    return 0;
    } char * retstring()
    {
    static char name[10];
    strcpy(name,"张汉青");
    return name;
    }
  • 这种方法在于采用了静态局部变量(位于静态区,程序结束时由系统释放),这会导致,下一次调用会将上次调用产生的结构进行覆盖。
  • 使用这样的函数应该立即将结构拷贝一份

使用全局变量

  •   char   g_s[100];
    char* fun()
    {
    strcpy(g_s, "abc ");
    return g_s;
    }

函数返回字符串问题

  • 归根结底,返回字符串就是要返回一个地址,同时需要保证地址在主调函数有效。
  • 直接定义char*变量,会保存在栈区,变量的作用域外会被立即销毁;malloc申请空间保存在堆区,需要手动销毁;静态区变量程序结束时销毁。
  • 所以返回一个地址要么扩大他的作用域,要么控制其生命周期。
  • 引用自:https://www.cnblogs.com/qingergege/p/6496683.html

C语言中函数返回字符串的4中方法的更多相关文章

  1. C语言中函数返回字符串的四种方法

    在讨论着四种方法之前,首先要对函数有一个简单的认识,无论是在形实结合时,还是在return语句返回时,都有一个拷贝的过程.你传进来的参数是个值,自然函数在工作之前要把这个值拷贝一份供自己使用,你传进来 ...

  2. c语言main函数返回值、参数详解(返回值是必须的,0表示正常退出)

    C语言Main函数返回值 main函数的返回值,用于说明程序的退出状态.如果返回0,则代表程序正常退出:返回其它数字的含义则由系统决定.通常,返回非零代表程序异常退出. 很多人甚至市面上的一些书籍,都 ...

  3. C语言strcat()函数:字符串连接(拼接)

    C语言strcat()函数:字符串连接(拼接)   C语言 strcat() 函数用来将两个字符串连接(拼接)起来. 头文件:string.h 语法/原型: char*strcat(char* str ...

  4. C函数返回字符串

    #include "stdio.h" #define KEY 5; int main() { char password[50] = "123456"; enc ...

  5. Oracle function real_st_astext,解决ArcSDE中st_astext函数返回字符串结构异常问题

    项目过程中发现在Oracle中调用ArcSDE的st_astext函数返回ST_Geometry类型字段的WKT文本有时空间类型前缀没有返回,例如一个点的经度为113.4,纬度为30.6,调用st_a ...

  6. SqlSever基础 Upper函数 返回字符串的大写形式

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  7. SqlSever基础 lower函数 返回字符串的小写形式

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  8. Go语言示例-函数返回多个值

    Go语言中函数可以返回多个值,这和其它编程语言有很大的不同.对于有其它语言编程经验的人来说,最大的障碍不是学习这个特性,而是很难想到去使用这个特性. 简单如交换两个数值的例子: package mai ...

  9. C语言之函数和字符串

    二.函数: 2.1.函数的执行: 1.当我们每次进入一个函数的时候,原函数的栈底进行一个备份,之后将当前函数的栈底和栈顶指针分作同一个. 2.此时我们就可以说产生了一个新栈,产生新栈之后会在新栈中申请 ...

随机推荐

  1. JS 语句

    JS 语句 JavaScript 语句 JavaScript 语句向浏览器发出的命令.语句的作用是告诉浏览器该做什么. 下面的 JavaScript 语句向 id="demo" 的 ...

  2. IntelliJ IDEA中你应该知道的快捷键

    IDEA官方所有快捷键:参考:https://resources.jetbrains.com/storage/products/intellij-idea/docs/IntelliJIDEA_Refe ...

  3. 设置API:wx.openSetting,wx.getSetting使用说明(示例:地图授权与取消授权后的重新授权)

    这个API解决了过去一个长久以来无法解决的问题,如何让用户重复授权: 打开小程序的设置界面:就是主动调取授权 目前资料极少,但是已经可以让大家先看看了: 官方文档地址:https://mp.weixi ...

  4. Python升级PIP

    用pip list的时候.发现最后有两行黄颜色的.提示你可以用‘python -m pip install --upgrade pip’升级你的pip 当时我直接就复制粘贴上去运行了.但是报了一堆红的 ...

  5. bootrom/spl/uboot/linux逐级加载是如何实现的?

    关键词:bootrom.spl.uboot.linux.mksheader.sb_header.mkimage.image_header_t等等. 首先看一个典型的bootrom->spl-&g ...

  6. IntelliJ 注解@Slf4j后找不到log问题解决

    解决方案:IntelliJ IDEA安装lombok插件可以解决以上问题 .步骤:1.找到IDEA 上方的菜单栏 点击File =>Settings,或者按快捷键Ctrl+Alt+S. 2.如图 ...

  7. 9. java API使用 - Scanner类

    一.API概述和使用 1. 概述 ​ API(应用程序编程接口).Java API是一本程序员字典,是JDK提供给我们使用的类的说明文档.这些类将底层的代码实现封装了起来,我们不需要关心这些类是如何实 ...

  8. 对比keep-alive路由缓存设置的2种方式

    方式有两种 .路由元信息(2.1.0版本之前) .属性方式(2.1.0版本之后新增) Vue2.1.0之前: 想实现类似的操作,你可以: 配置一下路由元信息 创建两个keep-alive标签 使用v- ...

  9. 浅谈JS重绘与回流

    在说浏览器渲染页面之前,我们需要先了解两个点,一个叫 浏览器解析 URL,另一个就是本章节将涉及的 重绘与回流: 重绘(repaint):当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新, ...

  10. 面向对象程序设计(JAVA) 第12周学习指导及要求

    2019面向对象程序设计(Java)第12周学习指导及要求 (2019.11.15-2019.11.18)   学习目标 (1) 掌握Vetor.Stack.Hashtable三个类的用途及常用API ...