嵌入式学习Day11 C语言 --- 数组作为函数的形参、标识符的作用域与生命周期
2026/8/18 13:25:05 网站建设 项目流程

一、数组作为函数的形参

1.一维整形数组做函数形参
//形式上
void printArray(int a[],int len);
//实际上
void printArray(int *a,int len); //指针的形式
2.一维字符型数组做函数形参
//形式上
void printStr(char s[]); //字符串有结束标志
//实际上
void printStr(char *s); //字符串有结束标志

3.二维整形数组做函数的形参

形式上: //形参 --数组形式,行数
void printArray(int a[3][4],int row);

实际上:
void printArray(int (*a)[4],int row); //编译器 的最终解释

实参:
printArray(a,row); //数组名 行数


int a[3][4] ---int a[][4]

int[4] a[];

练习:
定义一个二维整型数组,实现一个函数,
对二维数组元素求和

4.二维字符型数组做函数形参:
char s[3][10] = {"hello","world","china"};

形式上:
void printStr(char s[][10],int row) //注意需要传行数,因为操作多个字符串

本质上:
void printStr(char (*s)[10],int row)

实参:
printStr(s,row); //数组名 行数

练习:
准备3个字符串
实现函数 找出最大值

练习:
准备3个字符串
排序


二、标识符的作用域和可见性问题,生命周期

栈中存储

局部变量:函数内部定义的变量,其作用域仅限于该函数。比如在一个C语言函数中定义的整型变量 int num = 10;,当函数被调用时,这个变量就会被压入栈中。函数执行结束后,这些局部变量所占的栈空间会被释放。
函数形参:函数调用时传递的参数也会被保存到栈里。例如在调用 func(int a, int b) 函数时,实参的值会被复制到栈上传递给函数,这样函数内部就可以使用这些参数进行运算。
返回地址:记录函数调用结束后要返回的程序位置。当一个函数调用另一个函数时,会把当前函数的下一条指令地址压入栈中,被调用函数执行完毕后,会根据栈中保存的返回地址返回到原函数继续执行。

中断上下文

程序状态:在发生中断(如硬件中断、软件中断)时,会把当前程序的状态信息(如寄存器的值)保存到栈中。以微处理器为例,当中断发生时,会将程序计数器(PC)、状态寄存器等的值压入栈。中断处理程序执行完后,再从栈中恢复这些信息,使程序能够从中断处继续执行。

堆区

在操作系统为进程分配的内存空间里,堆区是其中一部分。它由程序员手动管理,用于动态分配内存。与栈区(由系统自动分配和释放内存)不同,堆区为程序提供了更灵活的内存使用方式,允许程序在运行时根据实际需求来决定分配和释放内存的时机和大小。使用malloc()calloc()realloc()等函数来请求操作系统分配指定大小的内存块。使用free()函数来释放之前用malloc()等函数分配的内存。如上述C语言代码中,在使用完arr后,需要添加free(arr);来释放内存。

作用域:
作用的范围

局部变量 --- 一定在某一个{} 范围内
全局变量 --- 不在任何一个{} 范围内

可见性:
程序运行到某个点,哪些标识符可见

标识符的可见性的规则:
1.先定义,后使用
2.同一作用域中,不能有同名标识符
3.在不同的作用域,同名标识符,相互之间没有影响
4.如果是不同的作用域,
但是作用域之间存在嵌套关系,则, 内层的作用域的同名标识符,会屏蔽外层的作用域的同名标识符(就近原则)


生命周期:
动态变量(局部变量)的 (生命周期):
从定义的语句开始,到所在的作用域范围结束
eg:
栈上的是局部变量 ( 自动申请 自动释放 )

全局区(静态区)上的是 静态变量 (全局变量)
从程序一开始运行,就存在,直到程序结束时,销毁

注意:
全局变量(静态变量)

1.不能用变量进行初始化,只能常量初始化 int a = 10; //true int b = a;//error

2.静态区的变量
只会被初始化一次 int a ; a = 10; //error int a = 10; //true int a; //true

for(i = 0;i < 3;i++) { static int b = 0; b++; printf("b = %d",b); //打印三次,分别是 b = 1,b = 2,b = 3 }

3.值具有 继承性



auto int a; //这个是一个自动变量 --- 栈上开辟的变量
static int a; //静态区
//修饰的是 局部变量
register int a; //CPU 寄存器
//建议性
考点:
不能 & (取地址),因为是cpu内部的寄存器,取地址运算是取得内存的地址

register int i; 将变量存储在寄存器中,提高访问速度
for( i = 0; i < 100000000; ++i)
{
}


extern int a; //扩展 延伸
//表示 此时这个a 不是在当前文件中定义的 ,
//如果要用,请到别的文件中寻找
//多文件编程
//一般使用在多文件编程中:
//如果想在当前文件使用别的文件中的 全局变量 ,
//此时,可以使用
//extern int a; //做声明
//相当于,把别的文件中的变量作用域扩展到当前文件

//全局变量前面
static 修饰局部变量
//将局部变量 存储在了 全局区(静态区)
//将局部变量的生命周期延长 ,作用域不变 //只能被初始化一次

#include <stdio.h> void function() { static int counter = 0; // 使用 static 修饰的局部变量 counter++; printf("Counter: %d\n", counter); } int main() { function(); // 第一次调用 function 函数 function(); // 第二次调用 function 函数 function(); // 第三次调用 function 函数 return 0; }

在上述代码中,function 函数内部定义了一个 static 局部变量 counter 并初始化为 0。当第一次调用 function 函数时,counter 被初始化为 0,然后递增为 1 并输出。当第二次调用 function 函数时,counter 不会再次被初始化为 0,而是保持上一次调用后的值 1,然后递增为 2 并输出。同样,第三次调用时,counter 保持上一次的值 2,递增为 3 并输出

static 修饰全局变量
//表示 将全局变量 的作用域限定到本文件中
//别的文件中不能extern了
extern 可以放在函数声明中 --函数声明
//表示的意思 --将函数作用域扩展到当前文件
static 加在函数前面
// 此时效果与修饰全局变量效果一样
// 将函数作用域限定到本文件中

面试题:
1.你知道static吗?

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

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

立即咨询