C语言部分(谭浩强C语言程序设计)
首先要了解什么是全局变量
全局变量又叫外部变量:在函数外定义,可为本文件所有函数公用,也叫外部变量.
有效范围:从定义变量的位置开始到本源文件结束,及有extern说明的其他的源文件
demo
#include <stdio.h>
int a = 10; //全局变量(定义在函数外部)
int subNum(int,int);
int getNumA();
int main(int argc, const char * argv[]) {
// insert code here...
int b = 20;
int c = subNum(a,b);
int d = getNumA();
printf("a = %d, b = %d, c = %d\n", d, b, c);
// printf("subNum Func e = %d", e); //全局变量e是在函数main的后面定义的,所以int e = 3;后面的代码中可以使用,前面不可以使用,会报错
return 0;
}
int e = 3; //全局变量(定义在函数外部)
int subNum(int a, int b)
{
printf("subNum Func e = %d\n", e);
return a + b;
}
int getNumA()
{
printf("getNumA Func e = %d\n", e);
return a;
}
接下来,我们再创建一个.c文件来印证全局变量可以在有extern说明的其他源文件
ReferenceGlobalVar.c文件
#include <stdio.h>
extern int e;
int main()
{
printf("ReferenceGlobalVar e = %d\n",e); //打印结果 ReferenceGlobalVar e = 3
return 0;
}
全局变量的使用,增加了函数间数据联系的渠道,同一文件中的所有函数都能引用全局变量的值,当某函数改变了全局变量的值时,便会影响其他的函数.
使用注意:
1>习惯上,全局变量名的第一个字母用大写(所以上面定义的全局变量int a=10;int e=3;应该改成大写的int A = 10; int E = 3;才比较规范,这里就不再修改了)
2>使用全局变量可以减少函数实参和形参的个数
3>不必要时不要使用全局变量,因为1)全局变量在程序执行的全过程都占用存储单元2)不利于程序的移植.程序的可读性变差
4>全局变量与局部变量重名时,在函数内部将屏蔽全局变量
再重新创建一个.c文件来验证第四点GlobalVarRename.c
#include <stdio.h>
int A = 10;
int main()
{
printf("befor for A = %d\n", A);
for(int A = 0; A < 5; A++)
{
printf("for A = %d ", A);
}
printf("\nafter for A = %d\n", A);
return 0;
}
打印结果:
befor for A = 10
for A = 0 for A = 1 for A = 2 for A = 3 for A = 4
after for A = 10
所以for循环中用的是临时定义的变量A初始值为0,而for循环前后使用的都是全局变量A初始化值为10
接下来我们了解一下变量的分类:
按数据类型:整形,实型,字符型 (int,float,char)
按作用域:全局变量,局部变量 (函数内部/外部定义)
存储方式:
静态存储:程序运行期间分配固定的存储空间
动态存储:程序运行期间根据需要动态分配存储空间
变量的生存周期:
静态变量:从程序开始执行到程序结束
动态变量:从包含该变量定义的函数开始执行至函数执行结束
内存用户区:
静态存储区: 全局变量,局部静态变量
动态存储区: 形参变量,局部动态变量,函数调用现场保护和返回地址等
auto变量
函数内部无static声明的局部变量均为动态存储类别,被分配在动态区
存储类别为自动时,声明符auto可省;自动变量被分配到动态区,未赋初值时,其值未定义,每次调用重新赋值
auto int b,c=3; == int b,c=3;
用static声明局部变量
若希望函数调用结束后,局部变量的值保留,则指定该变量为静态局部变量,用static对变量加以声明
(局部静态变量具有可继承性)
#include <stdio.h>
void func();
int main()
{
func();
func();
func();
return 0;
}
void func()
{
static int i = 0;
i++;
printf("i = %d ", i);
}
输出结果:
i = 1 i = 2 i = 3
对静态局部变量的说明:
1)分配在静态区,程序运行结束释放存储单元
2)赋初值一次未赋初值时为0,前次保留结果
int main()
{
static int i;
printf("i = %d\n", i);
return 0;
}
输出结果:
i = 0
3)局部动态变量若未赋初值,其值不确定,局部静态变量未赋初值,其值为0或’\0’字符变量
int main()
{
static int i;
static char j;
int h;
printf("i = %d, j = %c, h = %d\n", i, j, h);
return 0;
}
输出结果:
i = 0, j = ,h = 1606422582
4)静态局部变量在函数调用结束后虽存在,但其他函数不能引用它
void func();
int main()
{
func();
func();
func();
// printf("i = %d", i);
func();
return 0;
}
void func()
{
static int i = 0;
i++;
printf("i = %d ", i);
}
main函数引用静态局部变量i就会报错
使用局部静态变量的场合
1)需要保留上一次调用结束时的值
2)初始化后变量只被引用而不改变其值,则用静态局部变量较方便,以免每次调用时重新赋值,但会一直占用内存浪费系统资源
C++中关键字使用
静态成员的提出是为了解决数据共享的问题.在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏性的原则,即保证了安全性.因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员.
使用静态数据成员可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。
静态数据成员的使用方法和注意事项如下:
1)静态数据成员在定义或说明时前面加关键字static。
2)静态成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下:
<数据类型><类名>::<静态数据成员名>=<值>
class A
{
public:
A();
~A();
private:
static int i;
};
.cpp文件中
int A::i = 0;
A::A(){ A::i = 10; }
A::~A(){}
这表明:
(1) 初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆。
(2) 初始化时不加该成员的访问权限控制符private,public等。
(3) 初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员。
3、静态数据成员是静态存储的,它使静态生存期,必须对他进行初始化
4、引用静态数据成员时,采用如下格式:
<类名>::<静态成员名>
如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员。
类中static成员函数
静态成员函数
静态成员函数和静态数据成员一样,他们都属于类的静态成员,他们都不是对象成员。因此对静态成员的引用不需要用对象名。
在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员。如果静态成员函数中要引用非静态成员时,可通过对象来引用。
读者可以自行分析其结果。从中可看出,调用静态成员函数使用如下格式:
<类名>::<静态成员函数名>(<参数表>);
class B
{
public:
B();
~B();
static void HelloWorld();
private:
static int i;
int j;
};
.cpp文件中
int B::j = 10;B::B(){}
B::~B(){}
void B::HelloWorld()
{
i++;
print("i = %d", i);
//不能直接引用j,会报错
}