有时,如果程序有更多的功能。 规模比较大。 将所有程序代码都写在一个main函数中会使main函数变得过于复杂。 因此,为了方便程序的阅读和维护,引入了汇编程序的概念,部分功能在其他分支中完成。 ,然后在需要函数的时候将该分支汇编到主函数中,这些分支称为函数,汇编称为调用,这样会简化主程序,明确哪个函数做什么。 无论你在哪里需要这个函数,就在那里调用它!

C语言的函数可以直观地区分面向过程和面向对象的区别。 C语言的函数有一个特点,那就是它有固定的格式和固定的模型。 对于C程序来说,它的所有命令都包含在函数中。 每个函数执行特定的任务。 每个函数只能定义一次。 但函数可以根据需要多次声明和调用。

函数定义

函数必须在使用之前定义。

f245dbf8-4870-11ed-a3b6-dac502259ad0.png

定义一个函数以包括:

1.为后续调用返回值指定函数的数据类型

2.指定函数名,以便后续调用

3、指定函数形参的类型和名称,以便后面可以传递数据。 对于无参数(void)则不需要

函数类型+函数名+(参数表){  
  函数体
}

参数值的()在表示函数调用中起着重要作用。 即使没有参数,()也是必需的。 如果有参数,需要给出正确的数量和顺序。 这些值会按照一定的顺序(看编译环境,一般是从右到左)依次初始化函数中的参数

注意,如果调用函数时给定的值与参数的类型不匹配,有些编译环境可能会帮你进行类型转换,但可能不是你想要的。所以建议传递给函数的值保持一致与声明

#include//这里声明的是int的形参
int a(int a);//但是如果换成浮点类型输出将会不一样
int main(void){   
 double t = 23.8; 
   a(t);//这里传进去的是浮点数(实参)
}
int a(int a){//这里接收到的是整型的实参  
  int t = a;   
 //所以即使换成double t 也一样   
     printf("%d", t);//输出23
} 
 //但是更高级的语言会检查比较严格如 java C++

函数按值传递

每个函数都有自己的变量空间,参数也位于这个独立的空间中,与其他函数无关

值的传递:传递给函数的值可以是表达式的结果(包括):文字、变量、函数返回值、计算结果。 但调用函数时,永远只能向函数传递一个值。 传递值时,实际上只是将实参的值传递给形参,所做的只是一个复制的过程(但指针不同)

函数定义的形参中,它们不占用内存,在主函数中调用形参的值时会临时分配内存。 实参到形参的传递就是值的传递,是一种单向传递。 将实参的值传递给形参。 调用结束后,形参的存储单元被释放,形参值的任何改变都不会影响实参的值。 实际参数的存储单元仍然保留并保持该值恒定。

地址的传递:形参为指针变量时函数之间的数据传递。 如果函数的形参是指针类型,则对应的实参类型必须与形参类型一致

该方法使用数组名或者指针作为函数参数,传递数组的首地址或者指针的值,而形参则接收地址,即指向实参的存储单元,并且形参和实参占据相同的空间。 存储单元,这种传输方式称为“参数地址传输”。

地址传递的特点是形参不占用存储空间,数组名或指针是一组连续空间的首地址。 因此,当数组名或指针作为函数参数时,传输只是地址传输。 获得形参首地址后,它与实参一起存在于一个存储单元中,形参的改变也是实参的改变。

函数返回值

定义时,如果不需要返回值就定义void类型,其他时候定义其他数据类型。但是使用void类型时,不能使用值(可以没有),也可以调用时不指定返回值

int 和 void 的区别:

void 前面的函数不能返回任何数据。 这种函数应该实现该函数中所有应该实现的功能。 但与外界交换数据也不是不可以,仍然可以通过引用参数传递数据,但是调用时不能直接接受返回值,因为没有返回值。

对于前面有int的函数,返回值是一个整数,可能是整数,也可能是运行状态、成功或失败标志。 函数调用时,可以直接利用返回信息来实现某些功能。

main() 函数揭秘

main() 函数原型: int main(int argc, char const*argv [ ] )

里面的两个参数允许从执行环境传入的任意多字节字符串(argv[0])作为命令本身,而命令行参数存储在argv[]中,这是C/C++规定的语言和可执行程序程序本身的文件名和地址,其中之一描述了命令行参数的数量,通常称为argc; 另一个是命令行参数数组,通常称为argv。 命令行参数都是字符串,所以argv的类型是char *[argc+1]。 程序的名称也以argv[0]的形式传入,参数列表总是以0结尾,即argv[argc]==0。 (argv数组的最后一个元素存储NULL指针)

#include 
int main(int argc, char * argv[]){   
 //argv[0]== 调用函数时使用的程序名和地址  
  //argv[1]==参数1   
 //argv[2]==参数2 
  //argv[3]==参数3 
   //依次类推...   
 //argc 就是计算并保存总共有多少个参数的  
  int i;   
 for (i = 0; i < argc; i++)    { 
       printf("%s
", argv[i]);   
 }    
return 0;
}

传递给主函数的两个参数,argc 和 argv。 argc是int类型,表示命令行参数的个数。 不允许用户传递,会根据用户从命令行输入的参数个数自动确定。 argv是char**类型,其作用是存储用户从命令行传入的参数(黑窗中输入)。 它的第一个成员是用户正在运行的程序的名称。

main函数的返回值用来描述程序的退出状态。 如果返回0,则表示程序正常退出; 返回其他数字的含义由系统决定。 通常,返回非零意味着程序异常退出。 (一般由

神奇的使用

(是C语言的关键字) 函数定义什么样的返回类型,函数就应该是相应类型的值。

在函数中,如果遇到一条语句,程序就会返回到调用该函数的下一条语句的执行,也就是说会跳出函数的执行,回到原来的地方继续执行。 但如果在主函数(main)中遇到该语句,那么整个程序就会停止。 表示从被调用函数返回到调用函数或其他函数继续执行,返回时可以附加一个返回值,返回值可以是常量、变量或表达式。 传递指针形式:将变量的地址直接传递给函数。 由于被调用的函数在参数指针的范围内,所以此时直接改变了变量的主体。

返回值:计算结果表示函数执行是否顺利(-1、0) 返回值可以是各种数据类型,如:int、float、char、a[array]、*a(指针) 、结构或类。 写作风格清晰,可以防止一些意外错误。 有时我也想中断函数的执行并返回到调用函数。

返回局部变量的地址是危险的。 返回全局变量或静态局部变量的地址是安全的。 在函数中返回内存是安全的,但很容易引起问题。 最好的方法是返回传入的指针。

在函数中调用函数本身:即本身=递归

#include//输出直到n项的斐波那契数列
int add(int n);int i;
int main(void) {   
     int n;  
  scanf("%d", &n); 
   int c;     
   for (i = 1; i <=n; i++) {//输出数列   
     c = add(i);//调用函数    
    printf("%d ", c);   
 }   
 return 0;
}int add(int n) {//递归  
  if (n == 1) {//第一位数是1    
    return 1;   
 }  
  else if (n == 2) {//第二位数也是1      
  return 1;   
 } else {  
      return (add(n-1) + add(n - 2));//第三位开始  等于它前两位相加 1+1=2 所以第三位是2  
  }
}

局部变量和全局变量的补充

局部变量的规则:

局部变量是在块中定义的:可以在功能块中定义,也可以在语句块中定义,甚至可以画一对大括号来定义变量。

但在程序进入这个块之前,这个块中定义的变量并不存在,离开这个块就消失了。

因此,在块外定义的变量在变量内仍然有效,但在块内定义的变量在块外无效。

注意:如果在块外部定义了与内部同名的变量,则内部变量将覆盖外部值(较小的变量覆盖较大的变量)。

同一个块中不能定义同名变量,局部变量不会被初始化,参数再次进入函数时会被初始化。

局部变量的规则:

未初始化的全局变量将获得零值,指针将获得 NULL。 全局变量只能用编译时已知的值来初始化,并且它们的初始化是在主函数之前。

注意:尽量不要使用全局变量在函数之间传递参数和结果。 尽量避免使用全局变量(丰田的情况),使用全局变量和静态局部变量不是线程安全的。

好了,今天的主题就讲到这里吧,不管如何,能帮到你我就很开心了,如果您觉得这篇文章写得不错,欢迎点赞和分享给身边的朋友。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注