作用域
作用域是程序中的一个区域,在该区域内定义的变量可以被访问,超出该区域则无法访问。在C语言中,变量可以在三个地方声明:
1. 局部变量
在函数或块内部声明的变量称为局部变量。
特点:
-
只能被该函数或代码块中的语句使用
-
在函数外部不可见
-
生命周期仅限于函数执行期间
示例:
c
#include <stdio.h>
int main() {
/* 局部变量声明 */
int a, b;
int c;
/* 实际初始化 */
a = 10;
b = 20;
c = a + b;
printf("value of a = %d, b = %d and c = %d\n", a, b, c);
return 0;
}
2. 全局变量
在所有函数外部定义的变量称为全局变量。
特点:
-
在程序的整个生命周期中都保留其值
-
可以被程序中的任何函数访问
-
在声明之后,在整个程序中可用
示例:
c
#include <stdio.h>
/* 全局变量声明 */
int g;
int main() {
/* 局部变量声明 */
int a, b;
/* 实际初始化 */
a = 10;
b = 20;
g = a + b;
printf("value of a = %d, b = %d and g = %d\n", a, b, g);
return 0;
}
3. 形式参数
函数参数定义中的变量称为形式参数。
特点:
-
在函数中被视为局部变量
-
优先于全局变量
示例:
c
#include <stdio.h>
/* 全局变量声明 */
int a = 20;
int main() {
/* main函数中的局部变量声明 */
int a = 10;
int b = 20;
int c = 0;
printf("value of a in main() = %d\n", a);
c = sum(a, b);
printf("value of c in main() = %d\n", c);
return 0;
}
/* 相加两个整数的函数 */
int sum(int a, int b) {
printf("value of a in sum() = %d\n", a);
printf("value of b in sum() = %d\n", b);
return a + b;
}
作用域优先级规则
当局部变量和全局变量同名时:
-
局部变量优先于全局变量
-
形式参数优先于全局变量
示例:
c
#include <stdio.h>
/* 全局变量声明 */
int g = 20;
int main() {
/* 局部变量声明 */
int g = 10;
printf("value of g = %d\n", g); // 输出10,局部变量优先
return 0;
}
变量初始化
局部变量:
-
系统不会自动初始化
-
必须手动初始化,否则包含垃圾值
全局变量:
-
系统自动初始化
-
初始化规则:
-
int
类型初始化为 0 -
char
类型初始化为 '\0' -
float
类型初始化为 0 -
double
类型初始化为 0 -
指针类型初始化为 NULL
-
良好实践: 总是初始化变量,避免不可预知的结果。
数组
数组是一种数据结构,可以存储相同类型元素的固定大小顺序集合。
1. 数组声明
语法:
c
type arrayName[arraySize];
示例:
c
double balance[10]; // 声明一个包含10个double类型元素的数组
2. 数组初始化
方式1:声明时初始化
c
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
方式2:省略大小(自动计算)
c
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
方式3:单独赋值
c
balance[4] = 50.0; // 为第5个元素赋值
数组索引:
-
第一个元素索引为0(基索引)
-
最后一个元素索引为数组大小减1
3. 访问数组元素
示例:
c
#include <stdio.h>
int main() {
int n[10]; // n是包含10个整数的数组
int i, j;
/* 初始化数组元素为0 */
for(i = 0; i < 10; i++) {
n[i] = i + 100; // 设置位置i的元素为i + 100
}
/* 输出每个数组元素的值 */
for(j = 0; j < 10; j++) {
printf("Element[%d] = %d\n", j, n[j]);
}
return 0;
}
4. 多维数组
C语言支持多维数组,最常见的是二维数组。
声明语法:
c
type arrayName[x][y]; // 二维数组
type arrayName[x][y][z]; // 三维数组
二维数组初始化:
c
// 方式1:明确分行初始化
int a[3][4] = {
{0, 1, 2, 3}, // 第0行的初始化
{4, 5, 6, 7}, // 第1行的初始化
{8, 9, 10, 11} // 第2行的初始化
};
// 方式2:连续初始化
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
访问二维数组元素:
c
int val = a[2][3]; // 获取第3行第4列的元素
二维数组示例:
c
#include <stdio.h>
int main() {
/* 一个5行2列的数组 */
int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6}, {4,8} };
int i, j;
/* 输出每个数组元素的值 */
for(i = 0; i < 5; i++) {
for(j = 0; j < 2; j++) {
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
}
return 0;
}
5. 数组作为函数参数
三种声明方式:
方式1:指针作为形式参数
c
void myFunction(int *param) {
// 函数体
}
方式2:指定数组大小
c
void myFunction(int param[10]) {
// 函数体
}
方式3:不指定数组大小
c
void myFunction(int param[]) {
// 函数体
}
实际示例:
c
#include <stdio.h>
/* 函数声明 */
double getAverage(int arr[], int size);
int main() {
/* 包含5个元素的int数组 */
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
/* 传递数组指针作为参数 */
avg = getAverage(balance, 5);
/* 输出返回值 */
printf("Average value is: %f\n", avg);
return 0;
}
/* 计算平均值的函数 */
double getAverage(int arr[], int size) {
int i;
double avg;
double sum = 0;
for(i = 0; i < size; ++i) {
sum += arr[i];
}
avg = sum / size;
return avg;
}
6. 从函数返回数组
C语言不允许直接返回整个数组,但可以返回指向数组的指针。
重要注意事项:
-
不能返回局部变量的地址
-
必须将局部变量声明为
static
示例:
c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* 生成并返回随机数的函数 */
int *getRandom() {
static int r[10];
int i;
/* 设置种子 */
srand((unsigned)time(NULL));
for(i = 0; i < 10; ++i) {
r[i] = rand();
printf("r[%d] = %d\n", i, r[i]);
}
return r;
}
/* 主函数 */
int main() {
int *p; // 指向int的指针
int i;
p = getRandom();
for(i = 0; i < 10; i++) {
printf("*(p + %d) : %d\n", i, *(p + i));
}
return 0;
}
7. 指向数组的指针
数组名是指向数组第一个元素的常量指针。
重要概念:
-
balance
指向&balance[0]
-
*(balance + 4)
等同于balance[4]
示例:
c
#include <stdio.h>
int main() {
/* 包含5个元素的数组 */
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
int i;
p = balance; // p指向数组的第一个元素
/* 使用指针输出数组元素的值 */
printf("Array values using pointer\n");
for(i = 0; i < 5; i++) {
printf("*(p + %d) : %f\n", i, *(p + i));
}
/* 使用数组名作为地址输出数组元素的值 */
printf("Array values using balance as address\n");
for(i = 0; i < 5; i++) {
printf("*(balance + %d) : %f\n", i, *(balance + i));
}
return 0;
}
总结
-
作用域规则:
-
局部变量只在定义它们的函数或块中可见
-
全局变量在整个程序中可见
-
形式参数在函数中作为局部变量处理
-
-
数组特性:
-
存储相同类型元素的集合
-
支持一维和多维数组
-
可以通过指针操作
-
可以作为函数参数传递
-
可以通过返回指针从函数返回
-
-
最佳实践:
-
总是初始化变量
-
注意数组边界,避免越界访问
-
理解指针和数组的关系
-
在多维数组中正确使用嵌套循环
-
掌握作用域和数组的概念对于编写结构良好、高效的C语言程序至关重要。