一、变量的作用域和生命周期
1. 什么是作用域?
作用域就是变量在代码中的"可见范围",决定了在哪些地方可以使用这个变量。
2. 局部变量
定义位置:在函数内部定义的变量
作用范围:只在定义它的那对大括号 {} 内有效
#include <stdio.h>
void test()
{
int a = 10; // 局部变量a,只在test函数内有效
printf("%d", a); // 这里可以访问a
}
int main()
{
test();
// printf("%d", a); // 错误!这里不能访问a
return 0;
}
3. 全局变量
定义位置:在所有函数外面定义的变量
作用范围:从定义位置开始,到整个程序结束
#include <stdio.h>
int global_num = 100; // 全局变量
void fun1()
{
global_num = 200; // 可以修改全局变量
}
void fun2()
{
printf("%d", global_num); // 可以访问全局变量
}
int main()
{
fun1();
fun2(); // 输出200
return 0;
}
4. 变量生命周期
生命周期:变量从创建到销毁的时间
局部变量生命周期:
-
开始:执行到变量定义时
-
结束:离开所在的大括号时
全局变量生命周期:
-
开始:程序启动时
-
结束:程序退出时
#include <stdio.h>
void test()
{
int a = 0; // 每次调用test都会重新创建a
static int b = 0; // static变量只创建一次
a++;
b++;
printf("a=%d, b=%d\n", a, b);
}
int main()
{
test(); // 输出:a=1, b=1
test(); // 输出:a=1, b=2
test(); // 输出:a=1, b=3
return 0;
}
二、函数参数传递
1. 值传递(传值)
把变量的值复制一份传给函数,函数内修改不会影响原变量。
#include <stdio.h>
void change(int x) // x是num的副本
{
x = 100; // 修改的是副本
printf("函数内: x=%d\n", x);
}
int main()
{
int num = 10;
printf("调用前: num=%d\n", num); // 输出10
change(num);
printf("调用后: num=%d\n", num); // 还是10,没变!
return 0;
}
2. 地址传递(传地址)
把变量的地址传给函数,函数可以通过地址修改原变量。
#include <stdio.h>
void change(int *x) // x是指针,存放地址
{
*x = 100; // 通过地址修改原变量
}
int main()
{
int num = 10;
printf("修改前: num=%d\n", num); // 输出10
change(&num); // 传递num的地址
printf("修改后: num=%d\n", num); // 输出100,变了!
return 0;
}
3. 数组作为参数
数组作为参数时,传递的是数组的地址。
#include <stdio.h>
// 打印数组
void print_array(int arr[], int size)
{
for(int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
// 修改数组(会改变原数组)
void double_array(int arr[], int size)
{
for(int i = 0; i < size; i++)
{
arr[i] = arr[i] * 2;
}
}
int main()
{
int numbers[5] = {1, 2, 3, 4, 5};
printf("原数组: ");
print_array(numbers, 5);
double_array(numbers, 5);
printf("修改后: ");
print_array(numbers, 5);
return 0;
}
三、函数递归
1. 什么是递归?
函数自己调用自己。
递归三要素:
-
结束条件 - 什么时候停止
-
递归调用 - 调用自己
-
问题简化 - 每次调用问题要变小
2. 简单递归示例
#include <stdio.h>
// 示例1:倒数
void count_down(int n)
{
if(n < 0) return; // 结束条件
printf("%d ", n);
count_down(n - 1); // 递归调用
}
// 示例2:求1+2+...+n的和
int sum(int n)
{
if(n == 1) return 1; // 结束条件
return n + sum(n - 1); // 递归调用
}
int main()
{
printf("倒数: ");
count_down(5); // 输出:5 4 3 2 1 0
printf("\n");
printf("1+2+3+4+5 = %d\n", sum(5)); // 输出15
return 0;
}
四、宏定义和预处理
1. 基本宏定义
#include <stdio.h>
// 无参宏
#define PI 3.14
#define MAX_SIZE 100
// 带参宏
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main()
{
double r = 5.0;
double area = PI * r * r;
printf("圆面积: %.2f\n", area);
int num = 5;
printf("%d的平方: %d\n", num, SQUARE(num));
printf("5和3的最大值: %d\n", MAX(5, 3));
return 0;
}
2. 条件编译
根据条件决定编译哪些代码。
#include <stdio.h>
#define DEBUG 1 // 1表示调试模式,0表示发布模式
int main()
{
int x = 10, y = 20;
#ifdef DEBUG
printf("调试信息: x=%d, y=%d\n", x, y); // 调试时显示
#endif
int result = x + y;
printf("结果: %d\n", result);
return 0;
}
3. 头文件保护
防止头文件被重复包含。
// 在my_header.h文件中这样写: #ifndef _MY_HEADER_H_ // 如果没定义过_MY_HEADER_H_ #define _MY_HEADER_H_ // 就定义它 // 头文件内容... extern int add(int a, int b); #endif // 结束
五、重要概念总结
1. 变量类型对比
| 类型 | 作用域 | 生命周期 | 存储位置 |
|---|---|---|---|
| 局部变量 | 函数内 | 函数执行期间 | 栈区 |
| 静态局部变量 | 函数内 | 整个程序 | 数据区 |
| 全局变量 | 整个程序 | 整个程序 | 数据区 |
2. 参数传递对比
| 方式 | 特点 | 是否影响原变量 |
|---|---|---|
| 值传递 | 传递副本 | 不影响 |
| 地址传递 | 传递地址 | 影响 |
3. 编程建议
-
尽量使用局部变量,避免全局变量
-
宏定义中的参数要用括号括起来
-
递归一定要有结束条件
-
头文件要加保护,防止重复包含
947

被折叠的 条评论
为什么被折叠?



