C语言基础:函数(二)
2026/8/4 6:32:57 网站建设 项目流程

5,变量的存储类型

存储类型 数据类型 变量名; ​ 1. auto int a; 用的相对少 2. register int b; 用的相对少 3.extern int c; 4.static int d;
  1. auto , 自动存储类型 。 局部变量。 这个关键字 ,可以省略 。定义变量时,内存空间自动开辟,离开作用域是自动释放。内存的栈区(stack)。 函数内部定义的变量,函数的参数。

  2. register ,寄存器 . 建议编译器把某个变量存储在cpu的寄存器中。

    register int c;

  3. extern , 外部变量。 声明。 导出,目的是为了让其他的源文件,可以使用.

1.c #include <stdio.h> extern int a; // 声明,表示有这个变量,在其他的.c 中 extern int b; extern void fun(); int main() { int c = a+b; printf("a+b %d\n",c); fun(); } ​ ​ 2.c int a =10;// 定义,开辟内存空间 int b =20; ​ void fun() { } gcc 1.c 2.c

4.static 静态的

可以修饰变量,或函数。 用static 修改的变量,内存的数据区。

​ static 修改局部变量 如果局部变量前加 static ,变量的生命周期是整个程序运行的周期。 第一运行fun函数时, i, 分配空间+初始化。 如果不是第一次运行,这个变量 ,就不会在分配空间,和初始化。相当于 static int i = 0,这段没有 了。 ​ int fun() { ​ static int i = 0 ;// 全局生命周期 i++; return i; } ​ int main() { ​ int num = 0; printf("input num"); scanf("%d",&num); int j = 0 ; int count = 0 ; for(j=0;j<num;j++) { count = fun(); } // i = 20; //errror ,不能访问i。 i本身是存在,但是没在i的作用域范围内。 printf("count is %d\n",count); return 0; } ​

static 修饰全局变量的话,表示 这个变量只能在本模块(本源文件中 依然全局变量)中使用。其他的源文件 不可以使用。 static 的作用 限制作用域。

static 修饰函数的话。 static 的作用 限制作用域。 避免函数重名。

a.out 运行起来后的内存分布图

1,代码段, 存储的是编写的代码,二进制形式。只读。 2.数据段,全局变量,静态变量。没有给初值,系统全部初始化为0 。可读可写 3. 堆区,动态内存区。程序员手动申请和释放空间。最灵活 4.共享区, 库函数的实现。printf函数的定义。 5 栈区, 局部变量。函数的参数。 返回地址。内存自动申请,自动释放。

6,函数调用

调用前,必须先定义。

使用圆括号 ,(), 函数调用运算符。 add(); ,即使函数的调用,没有参数,括号不能省略。

如果需要传递参数话

  1. 传递参数的 个数保持一致

  2. 参数类型的需要匹配。

函数的调用过程 #include <stdio.h> void fun3() { printf("this is fun3...\n"); return ; } ​ void fun2() { fun3(); printf("this is fun2...\n"); return ; } ​ void fun1() { fun2(); printf("this is fun1...\n"); return ; } ​ int main() { fun1(); printf("this is main...\n"); return 0; } ​

函数参数的传递

  1. 值传递 , 实参把参数数据的内容通过赋值运算符给 形参的形式。 形参是实参的一个副本(复制品)。数据内容是相同的,实参的内存空间,和形参的内存,是独立。 没有办法通过修改形参来达到修改实参的目的。

    值传递只能读取实参的值, 不能就行修改。

#include <stdio.h> ​ void fun(int arg) { arg++; printf("fun arg:%d\n",arg); } void swap(int a,int b) { int t = 0 ; t = a; a = b; b =t; printf("swap a:%d b:%d\n",a,b); } int main() { int i =10; fun(i); printf("i:%d\n",i); ​ int a = 20; int b =1; swap(a,b); printf("main a:%d,b:%d\n",a,b); return 0; } ​

2.地址传递 ,实参传递变量的内存地址值。 即可以读实参的 数据的值 ,也可以修改。

一维整形数组做参数 , 本质是地址传递。

​ ​ void fill_array(int a[],int size)// int [] a; // 如果是整形数组的化,还需要数组的大小 { // 如果实参是数组类型,在被调内部,会降级为指针( 8 byte ,是数组在内存中的一个编号) // int size = sizeof(a)/sizeof(a[0]); int i = 0 ; for(i=0;i<size;i++) { // 这个不是值传递, 所以可以修改数组。 a[i] = rand()%30; } // printf("sizeof is a %lu\n",sizeof(a)); // printf("sizeof is a[0] %lu\n",sizeof(a[0])); } ​ int main() { srand(time(NULL)); int array[10]={0}; int size = sizeof(array)/sizeof(array[0]); fill_array(array,size);// int [] return 0; } ​ 函数版本 遍历 逆序 排序 ,冒泡,选择

一维字符数组的传参 , 本质是地址传递。

// 对于字符数组(字符串)而言, 约定以\0 结尾。 // 所用可以通过判断\0 的位置,可以得出字符串的长度。 // 所以不需要传入 size int mystrlen(char a[]) // 依然是地址传递,可以对数组对写操作 { // sizeof(a) == 8byte int len = 0 ; while(1) { if('\0'!=a[len]) { len++; } else { break; } } return len; } ​ int main() { char str[100]={0}; // char [] ​ printf("input string1:"); gets(str); // hello\0 int len =mystrlen(str) return 0; } 函数版本 遍历 mystrcmp mystrcpy mystrcat mystrlen ​

7,函数的递归

在函数内部,自己调用自己的函数调用,被称为函数的递归。

属于循环的一种 表现形式。 区别,会使用栈空间。

注意,

需要设置合理的退出条件。

递归的层次不要太深,会消耗大量的内存,可能导致程序崩溃。

应用,回溯类, 逆向思维的问题的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询