在谈变量之前首先需要了解一下c++的内存机制:
即:
进一步可以通过思维导图更加清晰的理解与记忆:
局部变量:在函数内部或复合语句内部定义的变量,在其作用域内有效(作用域{});
即:在一个函数内部定义的变量只在本函数范围内有效,也就是说只有在本函数内才能引用它们,在此函数外是不能使用这些变量的。在复合语句内定义的变量只在本复合语句范围内有效,只有在本复合语句内才能引用它们;
#include
using namespace std;
int add(int &m, int &n);
int main()
{
int a = 2, b = 3,c=0;
while (true)
{
int c;
int a = 4, b = 5;
c = add(a, b);
cout << "a+b=" << c << endl;
break;
}
c=add(a,b);
cout << "a+b=" << c<<endl;
return 0;
}
int add(int &m, int &n)
{
return m + n;
//return m+n+c;此句话的目的验证(1);
}
a+b=9
a+b=5
请按任意键继续. . .
这个结果显然易见,但是本次实验最重要的目的在于:
(1).a=2,b=3,c=0的作用范围是整个main函数(从“{”到“}”),哪add()函数也在这个范围内,哪么在add()函数范围内,.a=2,b=3,c=0还成立吗?答案是否定的。
这是由于函数调用的规则决定,执行add()函数,程序会自动跳转到add()函数范围内,这个范围内超出了a,b,c的作用域,所以无效。
既然如此,如果将add()函数定义成内联函数,此时a,b,c是否有效?然而结果是否定的
#include
using namespace std;
inline int add(int &m, int &n);
int main()
{
int a = 2, b = 3,c=0;
while (true)
{
int c=0;
int a = 4, b = 5;
c = add(a, b);
cout << "a+b=" << c << endl;
break;
}
c=add(a,b);
cout << "a+b=" << c<<endl;
return 0;
}
inline int add(int &m, int &n)
{
return m + n+c;
}
1.主函数中定义的变量(如a,b,c)也只有在主函数中有效,并不因为在主函数中定义而在整个文件或程序中有效。主函数也不能使用其他函数中定义的变量;
2.不同函数中可以使用同名的变量,他们代表不同的对象,互补干扰。
3.形参也是局部变量;
4.在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效;
全局变量:在函数外部定义,作用范围从定义位置到程序结束;
有上面可以知道,从变量的作用域(即从空间)的角度来观察,变量可以分成全局变量和局部变量;
本节从另一个角度,即从变量值存在的时间(即生存期)来观察。有的变量在程序运行的整个过程都是存在,**而有的变量则是在调用其所在的函数时,才临时分配存储单元,而在函数调用结束后该单元就马上释放了,变量不存在了。**也就是说变量的存储有两种方式:
静态存储方式:指在程序运行期间由系统分配固定存储空间的方式。
动态存储方式:在程序运行期间根据需要进行动态的分配存储空间;
由内存分配机制中可以看出,内存被分成三块区域,数据分别存储在静态存储区与动态存储区中;
在程序开始执行时分配存储空间,程序执行完毕后释放。在程序执行过程中,他们占据固定的存储单元,而不是动态地进行分配和释放;
在函数调用时分配存储空间,函数调用结束时就释放这些空间。在程序执行过程中,这种分配和释放是动态的,如果在一个程序中,两次调用同一函数,而在此函数中定义的局部变量,在两次调用时分配这些局部变量存储空间的地址可能是不相同的。
一次调用结束后其内存释放,下一次调用时重新分配内存;
一个完整的变量具有两种属性:数据类型与数据的存储类别。
数据类型如:整型、浮点型;
数据的存储类别:自动的(auto)、静态的(static)、寄存器的(register)、外部的(extern)
#include
using namespace std;
int main()
{
int display(int);
int a = 2, i;
for ( i = 0;i < 3; i++)
{
cout << display(a) << endl;
}
return 0;
}
int display(int a)
{
int b = 0; //自动局部变量
static int c = 3;//静态局部变量
b = b+1;
c = c + 1;
return a + b + c;
}
结果:7、8、9;
注意:
1.静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。
2.自动变量属于动态存储类别,分配在动态存储区域空间而不在静态存储区空间,函数调用结束后即释放。
3.对静态局部变量是在编译时赋初值,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数不在重新赋初值,而只是保留上次调用结束的值。
4.而对自动变量赋初值,不是在编译时候进行的,而是在函数调用时进行的,每调用一次函数重新给一次初值,相当于执行一次赋值语句;
这是由于,静态局部变量在程序运行的整个过程都会存在,在编译时赋值一次后,其局部静态变量的值将是一个确定的值(随程序执行可能改变,但是确定的,可控的),下一次调用时,其存储空间的值是上一次调用结束后的值。而自动变量,是在程序调用时才分配存储空间,所以其存储空间的初始值是未知的,是不可控的,为了安全起见,调用一次,初始化一次。
5.如果在定义局部变量不赋初值,则对静态局部变量来说,编译器会自动赋值0(数值类型变量)或‘\0’(字符型变量)。**而对于自动变量,他的值是一个不确定的值。**至于原因大家应该已经知道了,即由于每次函数调用结束后存储单元已经释放,下次调用时又重新分配存储单元,而所分配的单元中的内容是不可知的。
6.虽然静态局部变量在函数调用结束后仍然存在,但是其他函数是不能引用他的。因为他是局部变量,只能被本函数引用(只在其作用域内有效),而不能被其他函数引用;
3. 寄存器变量:几乎不用;
参考资料:《C程序设计<第四版>》谭浩强 著.北京:清华大学出版社。
图片来源:知乎,不知道先生;