精华内容
下载资源
问答
  • C语言strcpy函数的使用

    万次阅读 多人点赞 2020-04-19 11:00:53
    函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。 (B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记...

    strcpy简单使用: 

    #include <stdio.h>
    #include <string.h>
    
    struct Student {
    	int sid;
    	char name[20];
    	int age;
    
    } st;  //此处分号不可省略
    
    int main(void) {
    
    	struct Student st = {1000,"zhangsan",20};
    
    	printf("%d  %s  %d\n", st.sid, st.name, st.age);
    
    	st.sid = 500;
    	// st.name="lisi"  //error
    	strcpy(st.name,"lisi");
    	st.age=20;
    
    	while(true){}
    
    }

     

    头文件:#include <string.h> 和 #include <stdio.h>

    功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间

    说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。返回指向dest的指针

    //C语言标准库函数strcpy的一种典型的工业级的最简实现。 
    //返回值:目标串的地址。
    //对于出现异常的情况ANSI-C99标准并未定义,故由实现者决定返回值,通常为NULL。
    //参数:des为目标字符串,source为原字符串。
    char* strcpy(char* des,const char* source) { 
     char* r=des;    
     assert((des != NULL) && (source != NULL));
    while((*r++ = *source++)!='\0'); 
      return des; 
    }
    //while((*des++=*source++));的解释:赋值表达式返回左操作数,所以在赋值'\0'后,循环停止。

    举例: 

    char a[10],b[]={"COPY"};
    //定义字符数组a,b
    strcpy(a,b);
    //将b中的COPY复制到a中

    Strcpy函数中的缓冲区溢出问题和防范

    C 语言和 C++语言风格轻松、灵活,语法限制宽松,因而受到各类程序员的欢迎,是比较通用的编程语言,同时也是各大院校计算机专业的基本语言课程。strcpy 函数由于不对数组边界进行检查,而非常容易造成各种缓冲区溢出的漏洞。这些漏洞很容易被利用,而造成严重的系统问题。在使用 strcpy 函数时,要小心谨慎。
    以下就 Strcpy 函数中的缓冲区溢出问题和防范进行讨论。 [1] 

    缓冲区溢出问题

    缓冲区的溢出就是程序在动态分配的缓冲区中写入了太多的数据,使这个分配区发生了溢出。一旦一个缓冲区利用程序能将运行的指令放在有 root权限的内存中,运行这些指令,就可以利用 root 权限来控制计算机了。 [1] 

    Strcpy函数的安全编码

    在编程时,加入错误检查,就可及时发现错误,并且对出现的异常进行处理。在编写 strcpy 函数时,首先尽量使目的缓冲区长度足够长,另外要检测目的缓冲区和源缓冲区。如果目的缓冲区或源缓冲区是空,就要在异常处理中结束程序。如果,源字符串比目的缓冲区长度不长,也要在异常处理中结束程序,以防止出现溢出情况。任何程序都很难说是绝对安全,只能以尽可能安全的方式来处理 strcpy 函数。只要输入的字符串不以空字符结束,函数就会随时终止。这种检测容易实现。但是这样的检测也并不能确定函数一定安全。 [1] 

    另外,每添加一个错误检查,就会使程序更复杂,而且可能产生很多的 bug,增加很多的工作量。最重要的是,即使设计程序时非常仔细,也有可能会忽略一些细节问题,导致不可弥补的错误。所以,在编写程序时,最安全的方法,就是尽可能不去使用 strcpy 函数。可以在程序的开头加上 #define strcpy Unsafe_strcpy。这样,就会使 strcpy 函数在编译时产生错误,从而使我们在编程时可以完全摒弃strcpy 函数。在完全丢弃 strcpy 函数的同时,也就丢掉了众多依附于 strcpy 函数的 bug。 [1]

    特例说明

    已知strcpy函数的原型是:

    char * strcpy(char * strDest,const char * strSrc);

    1.不调用库函数,实现strcpy函数。

    2.解释为什么要返回char *。

    不调用库函数如何实现strcpy函数

    strcpy的实现代码

    char * strcpy(char * strDest,const char * strSrc){
    if ((NULL==strDest) || (NULL==strSrc)) 
      //[1]
      throw "Invalid argument(s)"; 
      //[2]
      char * strDestCopy = strDest; 
      //[3]
      while ((*strDest++=*strSrc++)!='\0'); 
      //[4]
      return strDestCopy;
    }

    错误的做法[1]:

    (A)不检查指针的有效性,说明答题者不注重代码的健壮性。

    (B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式

    (C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。

    错误的做法[2]:

    (A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。

    (B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。

    错误的做法[3]:

    (A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。

    错误的做法[4]:

    (A)循环写成while (*strDestCopy++=*strSrc++);,同[1](B)。

    (B)循环写成while (*strSrc!='\0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'\0'。

    解释为什么要返回char *

    返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函数,如果能合理地提高的可用性,自然就更加理想。

    链式表达式的形式如:

    int iLength=strlen(strcpy(strA,strB));

    又如:

    char * strA=strcpy(new char[10],strB);

    返回strSrc的原始值是错误的。其一,源字符串肯定是已知的,返回它没有意义。其二,不能支持形如第二例的表达式。其三,为了保护源字符串,形参用const限定strSrc所指的内容,把const char *作为char *返回,类型不符,编译报错。

    在上面的语句中,循环语句

    while ((*strDestCopy++=*strSrc++)!='\0');

    较难理解,可以把这句理解为以下操作。

    第一种:

    while( 1 ){    
      char temp;    
      *strDestCopy = *strSrc;  
      temp = *strSrc; 
      strDestCopy++;    
      strSrc++;   
      if( '\0' == temp )      
      break;
    }

     第二种:

    while ( *strSrc != '\0' ){
       *strDestCopy = *strSrc;
       strDestCopy++;
       strSrc++;
    }
     
    *strDestCopy = *strSrc;
       
    也即:
     
    while ( *strSrc != '\0' ){
       *strDestCopy++ = *strSrc++; 
    }
     
    *strDestCopy=‘\0’;

    使用实例

    //实例1:将一个字符串拷贝到一个足够长的字符数组中。本例中字符数组为a,长度为20。

    //缺点:若数组长度不足以容纳整个字符串,则程序运行崩溃。

    #include<iostream>
    #include<stdlib.h> 
    
    using namespace std; 
    char * strcpy( char * strDest, const char * strSrc ){  
      char * strDestCopy = strDest;  
      if ((NULL==strDest)||(NULL==strSrc))throw "Invalid argument";
        while ( (*strDest++=*strSrc++) != '\0' );
        return strDestCopy; 
    }
      
    int main( int argc, char * argv[] ){   
      char a[20], c[] = "i am teacher!";  
      try{   
           strcpy(a,c);
      }catch(char* strInfo){
           cout << strInfo << endl;
         exit(-1);
      }
       
      cout << a << endl;
      return 0;
     
    }

    //实例2:预设两个字符指针,一个指向字符串,另一个为NULL,在程序运行过程中拷贝。

    #include<iostream> 
    using namespace std;
     
    char *strcpy(char *strDes, const char *strSrc);
    //函数声明
     
    int main(){   
      const char *strSrc="helloworld";
      char *strDes=NULL;   
      strDes=strcpy(strDes,strSrc);   
      cout<<"strSrc="<<strSrc<<endl;   
      cout<<"strDes="<<strDes<<endl;   
      if(strDes!=NULL) { 
         free(strDes);
         strDes=NULL; 
      }    
      return 0; 
    }
     
    char *strcpy(char *strDes, const char *strSrc){   
      assert(strSrc!=NULL); 
      //若strSrc为NULL,则抛出异常。  
      strDes=(char *)malloc(strlen(strSrc)+1);
      //多一个空间用来存储字符串结束符'\0'   
      char *p=strDes;   
      while(*strSrc!='\0'){    
        *p++=*strSrc++;
      }
        
      *p='\0';  
     return strDes;
     
    }
    还有一种模拟算法:
     
    char * strcpy(char *dest ,const char *src){
        char *p=dest;
        while (*src != '\0'){
            *dest = *src;
            dest++;src++;
        }
        *dest = '\0';
        return p;
    }

    与strncpy的区别

    第一种情况:

    char* p="how are you ?";   
    char name[20]="ABCDEFGHIJKLMNOPQRS";  
        strcpy(name,p);
        //name改变为"how are you ? "====>正确!
        strncpy(name,p, sizeof(name));
        //name改变为"how are you ?" =====>正确!后续的字符将置为NULL

    第二种情况:

      char* p="how are you ?";
        char name[10];
        strcpy(name,p);
        //目标串长度小于源串,错误!
        name[sizeof(name)-1]='\0';
        //和上一步组合,弥补结果,但是这种做法并不可取,因为上一步出错处理方式并不确定
        strncpy(name,p,sizeof(name));
        //源串长度大于指定拷贝的长度sizeof(name),注意在这种情况下不会自动在目标串后面加'\0'
        name[sizeof(name)-1]='\0'; 
        //和上一步组合,弥补结果

     

     

     

     

    展开全文
  • 本函数手册涵盖了常用的C语言函数,从函数功能、参数和返回值三方面做了详细的说明,并且给出了大量实例,加深读者的理解。 为了方便大家查阅,我们已经将函数进行了分类。 1. 字符测试函数 2. 字符串...


    http://see.xidian.edu.cn/cpp/u/hanshu/


    本函数手册涵盖了常用的C语言函数,从函数功能、参数和返回值三方面做了详细的说明,并且给出了大量实例,加深读者的理解。


    为了方便大家查阅,我们已经将函数进行了分类。

    1. 字符测试函数 2. 字符串操作 3. 内存管理函数
    4. 日期与时间函数 5. 数学函数 6. 文件操作函数
    7. 进程管理函数 8. 文件权限控制 9. 信号处理函数
    10. 接口处理函数 11. 环境变量函数

    12. 终端控制函数

    展开全文
  • C语言system函数

    万次阅读 多人点赞 2018-01-04 10:53:44
    我们今天来看看在windows操作系统下system () 函数详解(主要是在C语言中的应用) 注意:在windows下的system函数中命令可以不区别大小写! 函数名: system 功 能: 发出一个DOS命令 用 法: int system(char *...

    我们今天来看看在windows操作系统下system () 函数详解(主要是在C语言中的应用)
    注意:在windows下的system函数中命令可以不区别大小写!
    函数名: system
    功 能: 发出一个DOS命令
    用 法: int system(char *command);

    system函数已经被收录在标准c库中,可以直接调用。

    例如:

    #include<stdio.h>
    #include<stdlib.h>
    int main()
    {
        printf("About to spawn and run a DOS command\n");
        system("dir");
    return 0;
    }

    又如:
    system(“PAUSE”)可以实现冻结屏幕,便于观察程序的执行结果;
    system(“CLS”)可以实现清屏操作。
    而调用color函数可以改变控制台的前景色和背景,具体参数在下面说明。

    例如:
    用 system(“color 0A”); 其中color后面的0是背景色代号,A是前景色代号。各颜色代码如下:

    0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色 A=淡绿色 B=淡浅绿色 C=淡红色 D=淡紫色 E=淡黄色 F=亮白色
    拿走不谢,我叫雷锋!


    在前面的第一个博客中我也写过一些DOS操作命令了大家想去了解的就去了解下。以下再给大家一些;

    这里写图片描述


    举例
    看了下面实例,相信你会对学到更多system在C程序设计中的应用。
    示例一:
    我们来试一试用C语言调用DOS命令实现定时关机,想想也很有趣,嘿嘿:大家可以给你朋友电脑上弄一个哦 让他输入我是猪才能不关机否则就关机了 。想弄其他字段的话自己去修改下程序中你给的字就可以了哦。可是大家别玩过火了哦。小心自己也解决不了哦。


    #include<stdio.h>     //标准输入输出库函数
    
    #include<stdlib.h>    //可以输入system用以键入DOS管理窗口界面下的cmd中的命令
    
    #include<string.h>    //字符串,数组定义的库函数
    
    int main()
    
    {
    
        char a[10];    //定义一个字符类型的数组,便于玩家从键盘键入各类字符信息
    
    flag:
    
        printf("请输入\"我是猪\",否则电脑将在两分钟后关闭\n");  //“我是猪”此语句可由制定者自由更改,不过后面相应的位置也要记得改动
    
        system("shutdown -s -t 120");    //60秒倒计时关机命令,时间可自由更改
    
        scanf("%s", a);             //玩家从键盘键入字符串
    
        if (strcmp(a, "我是猪") == 0){  //比较两个字符串,若相等则执行IF下的语句
    
            printf("恭喜你成功选择自己的属相,主动承认现实!\n");
    
            system("shutdown -a");  //结束自动关机倒计时命令,当然也可以打破规则,取消该语句,不过那样就太邪恶了
    
        }
    
        else
    
            goto flag;        //跳转语句,跳转至flag标记处继续执行
    
        return 0;
    
    }

    这个程序可以实现的是定时关机大家可以去试试哦

    #include<stdio.h>     //标准输入输出库函数
    
    #include<stdlib.h>    //可以输入system用以键入DOS管理窗口界面下的cmd中的命令
    
    #include<string.h>    //字符串,数组定义的库函数
    int print()
    {
        printf("****************关机程序****************\n");
        printf("****1.实现在十分钟内的定时关闭计算机****\n");
        printf("************2.立即关闭计算机************\n");
        printf("***************3.注销计算机*************\n");
        printf("****************4.退出系统**************\n");
        return 0;
    
    }
    void main()
    {
        system("title C语言关机程序");//设置cmd窗口宽度
        system("mode con cols=48 lines=25");//窗口宽度高度
        system("color 0B");//设置默认控制台前景个背景色
        system("date /T");
        system("TIME /T");
        char cmd[20] = "shutdown -s -t";
        char t[5] = "0";
        print();
        int c;
        scanf("%d", &c);
        getchar();
        switch (c)
        {
        case 1:
            printf("您想在多少秒后自动关闭计算机?(0~600)\n");
            scanf("%s", t);
            system(strcat(cmd, t));
            break;
        case 2:
            system("shutdown -p");
            break;
        case 3:
            system("shutdown -1");
            break;
        case 0:
            break;
        default:
            printf("Error!\n");
        }
        system("pause");
        exit(0);
    
    }

    示例二:
    用C语言删除文件,例如文件的位置是d:\123.txt
    用system()函数执行windows命令。

    #include<stdio.h>
    #include<stdlib.h>
    int main()
    {
        system("del d:\123.txt");
        return 0;
    }
    展开全文
  • C语言函数的基本知识

    万次阅读 多人点赞 2018-12-02 18:09:04
    1:函数C语言的模块,一块块的,有较强的独立性,可以相互调用,也就是说,你可以在函数A中调用函数B,又可在函数B中调用函数C,不仅如此,你还可以调用函数自身(递归)。 2:函数是完成一个个特定任务的语句集合...

    接着上次的数组,这次我们来简单的讲讲C语言里面的函数。
    函数和指针这两大块,在C语言中占据着重要的位置,是C语言中的主体和核心,所以它们的重要性也就不言而喻了。

    那什么是函数呢?
    1:函数是C语言的模块,一块块的,有较强的独立性,可以相互调用,也就是说,你可以在函数A中调用函数B,又可在函数B中调用函数C,不仅如此,你还可以调用函数自身(递归)。
    2:函数是完成一个个特定任务的语句集合,它能完成你所想要的某种特定任务,当你要用时,只需要调用它即可,在后续的修改或是维护过程中,只需要针对这一个进行修改即可。
    打个比方来理解函数:

    在一个饭店里面,顾客点了一盘菜后,服务员把该菜的名字给后勤,他负责洗菜这项功能,完毕后把菜交给配菜的师傅,待菜切好后,把菜交给厨师,厨师负责炒菜,完毕后,服务员把菜端给顾客。

    在上面那个比方内,有四个不同的,独立的角色:服务员,后勤,配菜师傅,厨师。
    他们每一个只是负责给他们指定的任务:
    服务员相当于是 main() 主函数,他是整个过程的开始,主函数也被称作 程序的接口,我们写的代码都是首先从这里执行下去的。
    后勤,配菜师傅,厨师, 相当于三个不同的函数,他们执行各自的功能,互不影响,并且哪里出了问题,很快就可以确定问题的位置。

    假如顾客吃到的菜有一只青虫,那我们基本可以确定出问题(bug)的是在后勤部分。

    那为什么需要函数呢?

    1:在我们写代码的时候,有时候会重复写一段代码,而这段代码所执行的功能,操作是一样的,只是针对的数据不一样,这个时候,将这段功能写成一个函数模块,在需要用到的时候调用即可,进而避免了写重复的代码,避免了重复性操作。
    2:方便代码的维护,当我们知道哪个部分出问题后,或者需要修改某个功能,那就只需要修改那部分的代码即可。
    在上面饭店的比方中,我们一下子便可知道吃到青虫时,是哪里出了问题。

    这里,我将上面那个例子,写成了一个点单的小程序,将洗菜配菜做菜分别写成了三个不同的函数来演示一下:
    在这里插入图片描述

    在主函数体外面:
    在这里插入图片描述
    这三个分别是独立出来的,完成他们各自的功能。互不影响,相互独立。
    若是不写成函数,那么直接在 case语句 后面分别写三条 printf ,那将会显得冗长,且如果有部分除了差错,那修改的将是三个,麻烦。


    库函数和自定义函数
    1: C语言为我们提供了上百个可调用的库函数,例如与字符串有关的 strlen, strcat, strlwr . 或是我们刚接触C语言时候用到的 printf, scanf, 这些都是c语言为我们提供的。在我们使用某一库函数的时候,需要在程序中嵌入(#include<>) 该函数所需要的头文件。
    这也就是为啥我们在代码开头都需要写上#include <stdio.h>,因为 printf, scanf,getchar,gets,putchar()这些函数 (也称作标准I/O函数),都是在stdio头文件中。
    2:自定义函数就是我们自己写的,例如我上面那个 chef(), coord()


    函数的定义
    这里记住一点即可:当你函数定义写在主函数之前的时候,那么就无需在主函数里面声明这个函数,只需要把函数体写在主函数前即可:
    在这里插入图片描述
    而若我将exp()写在下面:
    在这里插入图片描述
    那编译器将提示错误:
    在这里插入图片描述
    如果要写在主函数下面,我们则需要告诉编译器,有这个函数的存在:
    在这里插入图片描述


    函数按照是否有参数分为有参类型和无参类型

    按照是否有返回值也分为有返回值和无返回值两种类型。

    有参函数 指的是在该函数被调用的时候,主调函数通过参数向里面传递了数据。
    无参函数 很好理解就是不传递数据,因为没有参数,无法获得值。
    这里着重介绍下 有参函数
    它的定义一般是:

    函数数据类型 函数名字(参数1, 参数2, 参数3... , 参数n)
    {
       语句块;
    }
    //函数数据类型可以是 void (空类型,不带返回值的), int, float, double, 指针类型(int *, char *s)
    //参数,根据自己的需要来,你如果想传递浮点类型,那么就需要定义成浮点类型的数据类型(flaot, double)
    
    举例:
    //返回两个数字最大的一个
    int max(int n1, int n2)
    {
       return ((n1 > n2) ? n1 : n2);
    }
    
    //计算三个数字之和
    int sum(int n1, int n2, int n3)
    {
        return n1 + n2 + n3;
    }
    
    //计算字符串长度
    int _strlen(char *str)
    {
        int l = 0;
        while(*(str+l) != '\0' && ++l) ;
        return l;
    }
    

    在我们自定义的函数里面,括号里面的参数叫做形式参数(形参),而在主调函数里面,括号后面的参数叫做实际参数(实参),它可以是常量,变量,表达式
    例如你在主调函数调用max函数的时候可以:

    _max = max(12, 43);        //二者都是常量
    _max = max(n1 + n2, 4 * 5);  //n1 n2为变量,进行加法操作也是一个表达式
    

    在调用函数的时候,需要知道以下几点:
    1:在调用的时候,主调函数向参数传递的是值,在调用结束后,该值不改变。
    2:函数只有被调用,系统才会给它分配内存单元。
    3:调用结束后,系统给他分配的内存单元立即被释放,而主调函数中的值不会改变
    4:主调函数传递给被调用函数值后,被调用的函数里面可以直接用该值,但是要记住,值的数据类型要和参数的数据类型一一对应。

    第一点:
    函数再调用的时候,发生的是 值传递,也就是把值拷贝一份给形参,在形参里面改变其值并不影响实参的值<这里的值是单向传递的:实参 -> 形参 >:
    在这里插入图片描述
    在 exch() 函数中,我试图改变n的值,但是却没有改变,就是因为我仅仅只是把 n = 46 这个值给拷贝一份给了 exch() 函数,在此时的exch()函数中,它里面的n就有了 46这个值

    在这里插入图片描述

    对于第四点:
    在数据传递的时候,若是数据类型不同,有可能会发生数据丢失等错误,例如:
    在这里插入图片描述
    这里的数据发生了截断。


    函数的传递不仅有传值,也有传址的操作。

    传值就是直接用一个变量去存储那个值
    传地址就是用一个变量(指针变量)去记住那个地址

    这里需要了解一个知识点:
    1:数组名的值,就是一个一个指针常量。也就是第一个元素的地址,它的类型取决于数组元素的类型:如果它们是int类型,那么数组名的类型就是 “指向int的常量指针”;
    为啥说是常量,因为它在定义的时候系统已经给它分配好了内存地址,也就是说,已经是无法更改了。常量是不能被更改的量。
    2:如果你要在函数中,要改变主调函数中某变量的值,那么就要把地址传递给形参,
    如果不需要改变,直接传递值的拷贝即可。

    结合1,2两点可以理解为啥我们把数组名字作为实参传递进函数的时候可以改变原数组的值。
    数组的传递的方式:

    int sort(int arr[], int n);           //一维数组
    sotr(arr, 10);   					    //调用
    
    int sort(int *arr, int n);            //跟一维数组一样,指针的方式定义的
    sort(arr, 10);
    
    int sort(int arr[][4], int l, int r); //二维数组,需要告诉每个元素的数组长度
    sort(arr, 4, 4);
    

    有同学可能有疑问了,值传递和址传递有区别嘛?
    其实是没的,两者可以说是一样的,因为址传递,传递的是地址,地址这个值,由形参里面的指针变量存放着。

    看下面一个易错的例子:

    void swap(int a, int b)
    {
    	int t;
    	t = a;
    	a = b;
    	b = t;
    }
    

    我若调用

    swap(a, b);  //a = 2, b = 3;
    

    在主函数中,调用swap函数后,输出的结果是啥?
    答案依然是2,3
    为啥呢?
    因为我仅仅只是把 a = 2, b = 3 这个值给拷贝进了swap的形参中去,不影响主调函数中的变量的值。
    根据要注意的点中,第二个要点,我想在被动用的函数中就改变主调函数中参数的值,那么我就需要把地址传递进去,也就是进行址传递,那么我函数的定义就需要借助指针:
    在这里插入图片描述

    为什么会如此呢?
    因为我把变量的地址给传递进去了后,形参中的指针变量对地址进行的操作,就会影响该内存空间的值,进而反映到主调函数中去,也就是发生了改变。

    本次涉及到了指针的知识,指针又是一个比较难理解的地方,要理解指针,就需要的内存地址有一个深刻的理解,在学习指针的时候,可以用纸和笔在纸上勾画下 数据方框和地址方框,用箭头来表示指针指向地址方框来理解指针。
    函数后面还有更加复杂的递归函数,一句话来概括递归就是:递归是函数调用自身的过程。
    这里就不多做解释,因为我也并不是对递归有一个深刻的理解,所以也无法讲清楚来。

    <如有错误请指出>
    Gakki

    展开全文
  • C语言实现函数重载

    万次阅读 2017-04-09 22:58:49
    C语言实现函数重载 c语言中不允许有同名函数,因为编译时函数命名是一样的,不像c++会添加参数类型和返回类型作为函数编译后的名称,进而实现重载。如果要用c语言显现函数重载,可通过以下方式来实现: 使用函数...
  • C语言qsort函数用法

    万次阅读 多人点赞 2018-01-28 14:33:59
    qsort函数简介    排序方法有很多种:选择排序,冒泡排序,归并排序,快速排序等。 看名字都知道快速排序是目前公认的一种比较好的排序算法。因为他速度很快,所以系统也在库里实现这个算法,便于我们的使用...
  • C语言递归函数

    千次阅读 多人点赞 2018-09-03 14:14:21
    前言 ...从功能上来看:递归函数是一个函数C语言中,每个函数都代表一个独立的功能;递归函数当然也是一个功能函数; 从形式上来看:一种函数被自己本身调用的函数; 注意:递归虽说是函数本...
  • C语言 | 函数指针作为函数的参数

    万次阅读 多人点赞 2019-08-05 08:22:38
    函数指针有两种常用的用法,一种是作为结构体成员,关于函数指针作为结构体成员的用法可移步至上一篇【C语言笔记】函数指针作为结构体成员进行查看。另一种是函数指针作为函数的参数。这一篇分享的是函数指针作为...
  • C语言自定义函数的方法

    万次阅读 多人点赞 2019-04-13 21:44:53
    一、C语言之自定义函数的调用 1.声明一个自定义函数: void fun(void);//函数的声明 也可在主函数之前编写自定义函数; 2.主函数里调用自定义函数: int main(void) { fun();//调用fun函数; return 0; } 3.编写...
  • C语言strcmp函数

    万次阅读 多人点赞 2019-03-09 18:31:34
    调用字符串比较函数strcmp() 头文件为&lt;string.h&gt; 作用:比较a,b两个字符串的,strcmp函数是根据ASCII码来比较两个字符串的。用a字符串的第一个字符减去b字符串的第一个字符,若第一个字符相等,则...
  • 详解C语言指针函数函数指针、函数指针数组

    万次阅读 多人点赞 2018-07-09 11:08:24
    C语言中,指针是一个很重要但是又很容易弄错的概念,也可以说指针就是C语言的灵魂,所以说学好指针对于完全掌握C语言是一个必须的过程。而在指针中,指针函数函数指针、指针函数数组、函数指针数组、指向函数...
  • C语言atoi函数

    千次阅读 2020-04-14 09:58:39
    C语言提供了一系列函数把字符串转换为整数:atoi、atol、atoll和atoq。 1、包含头文件 #include <stdlib.h> 2、函数声明 int atoi(const char *nptr); long atol(const char *nptr); long long atoll(co...
  • C语言sort函数

    千次阅读 多人点赞 2019-08-21 09:23:21
    C语言的sort函数是一类用于数组排序的函数以下是其简单的使用: 1.头文件: #include<algorithm> 2.使用命名空间: using namespace std; 3.函数形式: sort(数组名,数组名+元素个数,排序函数); ...
  • C语言函数

    万次阅读 多人点赞 2019-08-03 19:54:19
    每个C程序都至少有一个函数,即主函数main(),如果程序的任务比较简单,全部的代码都写在main()函数中,但是,在实际开发中,程序的任务往往比较复杂,如果全部的代码都写在main()函数中,main()函数将非常庞大臃肿...
  • C语言外部函数与内部函数

    万次阅读 2017-12-18 17:09:11
    C语言中,根据函数能否被其他源文件调用,分为内部函数和外部函数 外部函数,可以被其他源文件调用的函数 内部函数,只在定义的文件中有效外部函数开发大型项目,可能包含很多源文件来分别实现,最终,再整合在...
  • C语言打印函数堆栈方法

    千次阅读 2017-05-21 22:46:27
    C语言打印函数堆栈方法
  • C语言函数的创建及使用

    千次阅读 2020-03-04 17:06:57
    C语言自创函数
  • C语言自定义函数如何返回数组

    万次阅读 多人点赞 2017-11-03 21:27:27
    C语言自定义函数如何返回数组  C语言研究中心  CTO 9个月前 (01-28) 4759次浏览 5个评论 最近看到一些同学问题,有提到说:如何在一个函数中返回数组呢? 能否直接在自定义 函数中,写成char *类型...
  • c语言对数函数log的使用

    万次阅读 多人点赞 2018-04-08 13:49:21
    c语言log函数使用:   #include&lt;stdio.h&gt; #include&lt;math.h&gt; int main(){ printf("%f\n",log(10)); //以e为底的对数函数 printf("%f\n",log10(100)); //以...
  • c语言getc函数 C语言中的getc()函数 (getc() function in C) Prototype: 原型: int getc(FILE *filename); Parameters: 参数: FILE *filename Return type: int 返回类型: int Use of function: ...
  • C语言malloc函数的功能及用法

    万次阅读 多人点赞 2018-12-18 08:01:18
    关于C语言malloc函数函数介绍应用举例1应用举例2 函数介绍 malloc(memory allocation) 中文名称:动态内存分配 用于申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址,当无法知道内存具体...
  • C语言函数指针和回调函数的详解

    万次阅读 多人点赞 2019-05-18 23:10:01
    函数指针:指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个...
  • C语言函数定义和函数声明

    万次阅读 多人点赞 2017-11-10 10:04:18
    C语言不同于Java语言,在Java语言中,在一个类中,定义函数/方法后,在调用时不需要声明。在C语言中定义函数后,在使用前,需要在main函数前进行声明,否则会报错。 #include //使用函数前,需要在main函数前对...
  • C语言 rand函数生成随机数

    万次阅读 多人点赞 2018-06-14 16:17:43
    在实际的项目中,有时候需要生成一个随机数,在C语言中随机数的生成可以通过使用rand函数来实现。 rand函数包含在头文件stdlib.h里,因此使用rand函数需要声明包含stdlib.h。 #include&lt;stdlib.h&gt; ...
  • C语言 三角函数用法

    千次阅读 2020-08-20 00:07:50
    C语言便准库中,要使用三角函数需要把度转变为弧度的形式,准换公式 deg/180*pi 测试 #include <stdio.h> #include <math.h> #define My_Pi 3.14159 /*******************************************...
  • C语言 strcpy函数实现

    千次阅读 2017-03-13 21:17:59
    前面写了用C语言关于字符串拷贝时可以用memcpy,其实不用memcpy也可以实现字符串的拷贝 —— strcpy专门针对字符串拷贝的函数,下面贴上linux实现方式。函数定义如下:char *strcpy(char *dest, const char *src);...
  • C语言abs函数

    千次阅读 2019-02-14 12:44:00
    C语言编程入门教程 - abs 函数是用来求整数的绝对值的。 //函数名:abs //功 能:求整数的绝对值 //用 法:int abs(int i); //程序例: #include<stdio.h> #include<math.h> int main(void) {...
  • C语言sleep函数与usleep函数

    千次阅读 2019-07-10 12:17:11
    函数名: sleep 头文件:#include <unistd.h> 功 能: 执行挂起指定的秒数 语 法: unsigned sleep(unsigned seconds); 举例: void father() { int i; for(i = 0 ;i < 3;i++) { printf("father\n")...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 693,668
精华内容 277,467
关键字:

c语言登录函数

c语言 订阅