double Area(double r); // r 在 左圆括号开始声明, 结束语右圆括号 , 在这个范围内r可以使用
void fun(int a) // a 的作用域 开始的位置
{
int b = a; // b 的作用域开始的位置
if (b>0)
{
int c; // c 的作用域开始的位置
......
} // c 的作用域结束的位置
} // a 的作用域结束的位置 , b 的作用域结束的位置
03-chigh/17-zuoyongyu.c
#include
int func(int a) // a = 1
{
int b = a;
{
int c = 10;
printf("1:c=%d\n", c);
}
printf("2:c=%d\n", c);
printf("1:b=%d\n", b);
printf("1:a=%d\n", a);
} // a 和b 的作用域结束位置
int main(int argc, char const *argv[])
{
func(1); // 调用函数 , 传递参数1
printf("2:b=%d\n", b); // b 在这个范围内, 没有定义
printf("2:a=%d\n", a); // a 在这个范围内, 没有定义
return 0;
}
17-zuoyongyu.c:10:24: error: ‘c’ undeclared (first use in this function)
printf("2:c=%d\n", c);
^
17-zuoyongyu.c:10:24: note: each undeclared identifier is reported only once for each function it appears in
17-zuoyongyu.c: In function ‘main’:
17-zuoyongyu.c:19:24: error: ‘b’ undeclared (first use in this function)
printf("2:b=%d\n", b); // b 在这个范围内, 没有定义
^
17-zuoyongyu.c:20:24: error: ‘a’ undeclared (first use in this function)
printf("2:a=%d\n", a); // a 在这个范围内, 没有定义
不在前述各个作用域中出现的声明,具有文件作用域,这样声明的标识符的作用域开始于声明点,结束于文件尾。
03-chigh/18-zuoyongyu.c
#include
// 不在块作用域内, 也不在函数原型的作用域, 这种作用域就是文件作用域 , 就是全局变量
// 从变量定义的位置开始, 到文件的结束
int a = 100 ; // 文件作用域
int func(int x) ; // x 是声明作用域
int main(int argc, char const *argv[]) //
{
int b = 10 ; // 块作用域
a=200;
printf("1:a=%d\n",a);
func(1);
return 0;
}
int func(int x)
{
a = 300 ;
printf("2:a=%d\n",a);
}
1:a=200
2:a=300
int i; //文件作用域 全局变量
int main()
{
i=5;
{
int i; //块作用域 局部变量
i=7;
printf("i=%d\n",i); // i=7 同名的变量, 作用域内的变量会屏蔽作用域外的同名变量
}
printf("i=%d\n",i); // i=5 作用域内内层中没有同名的变量, i在内层可见
return 0;
}
变量从产生到结束的这段时间就是它的生存期。在变量生存期内,变量将保持它的值,直到被更新为止。
linux@ubuntu:~/work/emb2207/03-chigh/35-static$ tree
.
├── build
├── CMakeLists.txt
├── main.c
└── src
├── beep.c
├── beep.h
├── led.c
└── led.h
2 directories, 6 files
#include
int * func(void)
{
int a = 100 ; // 后面加上 static 延长声明周期 为静态期
return &a;
}
int main(int argc, char const *argv[])
{
int * p = func();
printf("*p=%d\n",*p);
return 0;
}
19-shengcunqi.c: In function ‘func’:
19-shengcunqi.c:7:12: warning: function returns address of local variable [-Wreturn-local-addr]
return &a;
^~
段错误 (核心已转储)
块作用域中声明的,没有用static修饰的变量是动态生存期的对象(习惯称局部生存期变量)。
开始于程序执行到声明点时,结束于命名该标识符的作用域结束处。
例如
静态生存期与动态生存期
#include
void fun();
int main()
{
fun();
fun();
}
void fun()
{
static int a=1; // a 是块作用域(局部作用域) , 静态生存期 , static修饰的局部变量只能被初始化一次
int i=5; // i 是块作用域(局部作用域) , 动态生存期
a++;
i++;
printf("i=%d,a=%d\n",i,a);
} // 到这里时 i的值被销毁, a的值不销毁, 值也不变
// 第一次 func 输出 : i= 6 , a = 2;
// 第二次 func 输出 : i= 6 , a = 3;
03-chigh/20-zonghe.c
#include
int i=1; // i 为全局变量,具有静态生存期。
void other(void); // 函数声明
int main()
{
static int a; // 局部变量,块作用域 , 静态生存期,局部可见。 static 修饰的变量不赋值初始值, 初始值为0
int b=-10; // b为局部变量,块作用域, 动态生存期,局部可见 。
int c=0; // c为局部变量,块作用域, 动态生存期,局部可见 。
printf(<<"---MAIN---\n");
printf("i:%d a:%d b:%d c:%d \n",i,a,b,c);
c=c+8;
other(); // 第一次调用other();
printf("---MAIN---\n");
printf("i:%d a:%d b:%d c:%d \n",i,a,b,c);
i=i+10;
other(); // 第二次调用other();
}
void other(void)
{
static int a=2; //只第一次进入函数时被初始化。
static int b; // static 修饰的变量不赋值初始值, 初始值为0
// a,b 局部变量,块作用域 , 静态生存期,局部可见。
int c=10; // c 局部变量,块作用域 , 动态生存期,局部可见。
a=a+2;
i=i+32;
c=c+5;
printf("---OTHER---\n");
printf("i:%d a:%d b:%d c:%d \n",i,a,b,c);
b=a;
}
// 推算出 4次输出的结果
// 1: i=1 , a=0 , b=-10 , c=0
// c=8
// 2: i=33, a=4 , b=0 , c=15
// b=4
// 3: i=33, a=0 , b=-10 , c=8
// i= 43
// 4: i=75, a=6 , b=4 , c=15
// 计算机运算的结果:
---MAIN---
i=1 , a=0 , b=-10 , c=0
---OTHER---
i=33 , a=4 , b=0 , c=15
---MAIN---
i=33 , a=0 , b=-10 , c=8
---OTHER---
i=75 , a=6 , b=4 , c=15
程序在运行时, 可以带入参数 , 有main函数的参数进行获取
#include
int main(int argc, char const *argv[])
{
printf("argc = %d\n", argc); // argc : 表示参数的个数
// argv 是指针还是数组 , 是数组, argv先结合[] , 因此是数组
// 什么类型的数组, char const * 是修饰类型的 , 字符指针数组
// argv 是一个字符指针类型的数组,里面的元素是字符指针变量, 指针变量中保存字符串的起始地址
// argv 中的元素(字符指针变量)保存的是传入参数字符串的首地址
for (int i = 0; i < argc; i++)
{
printf("argv[%d]=%s\n",i,argv[i]); // argv[i]是数组的一个元素, 这个元素保存的是传入参数字符串的首地址
}
return 0;
}
argc :表示参数的个数
argv: 表示参数的内容
例如 , 获取运行程序时传入的参数的个数和内容
实例21
源文件
03-chigh/21-argc.c
#include
int main(int argc, char const *argv[])
{
printf("argc = %d\n", argc); // argc : 表示参数的个数
// argv 是指针还是数组 , 是数组, argv先结合[] , 因此是数组
// 什么类型的数组, char const * 是修饰类型的 , 字符指针数组
// argv 是一个字符指针类型的数组,里面的元素是字符指针变量, 指针变量中保存字符串的起始地址
// argv 中的元素(字符指针变量)保存的是传入参数字符串的首地址
for (int i = 0; i < argc; i++)
{
printf("argv[%d]=%s\n",i,argv[i]); // argv[i]是数组的一个元素, 这个元素保存的是传入参数字符串的首地址
}
return 0;
}
linux@ubuntu:~/work/emb2207/03-chigh$ ./21-argc 1.c 2.c 3.c 4.c
argc = 5
argv[0]=./21-argc
argv[1]=1.c
argv[2]=2.c
argv[3]=3.c
argv[4]=4.c
linux@ubuntu:~/work/emb2207/03-chigh$ ./21-argc
argc = 1
argv[0]=./21-argc
linux@ubuntu:~/work/emb2207/03-chigh$ ./21-argc 1.c
argc = 2
argv[0]=./21-argc
argv[1]=1.c
linux@ubuntu:~/work/emb2207/03-chigh$ ./21-argc 1.c 2.c
argc = 3
argv[0]=./21-argc
argv[1]=1.c
argv[2]=2.c
linux@ubuntu:~/work/emb2207/03-chigh$ ./21-argc 1.c 2.c 3.c
argc = 4
argv[0]=./21-argc
argv[1]=1.c
argv[2]=2.c
argv[3]=3.c