文章目录
一、对C语言程序的一些补充
对于一个代码:
#include<stdio.h>
#include <windows.h>
int main()
{
printf("hello world!\n");
system("pause");
return 0;
}
我们在编译运行的时候 会将这一段文本代码编译成为可执行程序,可执行程序就是一个二进制文件
。 在Windows当中,双击即可启动这个程序。因此在编译器中编译并运行,和在Windows下双击运行是等价的
对于obj等文件则是运行时产生的临时文件:
清理解决方案以后,Debug文件中的可执行文件和obj文件将会消失:
双击并运行这个可执行程序的本质,实际上是将程序的数据加载到内存当中,让计算机运行。
任何程序在被运行之前都必须被加载到内存当中。
所以程序在没有被加载到内存之前,程序在哪呢?
当没有被加载到内存之前,程序在硬盘(外设)当中。
各种设备和内存以及CPU的关系大致如下:
而之所以程序被运行之前要加载到内存中,是因为CPU访问内存的速度比直接访问输入设备要快很多
二、定义域声明
2.1.什么是变量
变量是程序在运行的时候在内存中开辟特定大小的空间,用来保存数据。
为什么变量要在内存中开辟而不是在硬盘中开辟呢?
因为变量是程序在运行的时候开辟的,程序在运行之后已经被加载到内存。也就是说,当我们要定义变量的时候,程序已经在内存里了,所以变量只能在内存中开辟空间。
换言之,虽然我们已经在编译器中定义了一个变量,但是这个变量并不会在我们写下这句代码的时候就开辟内存,而是必须要整个程序都加载到内存之后才会在内存中开辟空间。
2.2.如何定义变量
定义变量的方法想必大家都很熟悉,这里就不过多讨论了。
#include<stdio.h>
#include <windows.h>
int main()
{
char c = 'a';//初始化
c = 'b';//赋值
return 0;
}
初始化是在开辟空间时将内存空间中的内容进行修改,而赋值则是对已经开辟好的内存空间的内容进行修改。
2.3.为什么要定义变量
计算机是为了解决人的计算能力不足的问题而诞生的,也就是说计算机就是为了计算。
之所以需要变量,就是因为我们用计算机在做计算的时候,并不是所有的数据都被立刻进行计算的,这个时候,变量就需要被暂时保存起来,等需要的时候再使用。
2.4.定义变量的本质
从上面的内容我们已经明白:
- 程序运行,需要加载到内存中
- 程序计算,需要使用变量
定义变量的本质:在内存中开辟一块空间,用来保存数据。(为何一定是内存:因为定义变量的时候,程序已经被加载到内存当中)
2.5.变量声明的本质
一般来说,声明是加了 extern 关键字
extern int a; // 声明
声明就是告诉编译器,这个变量已经在别的地方定义过了,这个只做基本的声明,这个过程并没有为其分配内存。
2.6.定义和声明的区别
声明、定义的本质的区别在于有无分配内存。
声明只是告诉了编译器存在这么一个变量或者函数,这个函数或者变量在其他的位置定义过了,所以在这个过程中没有为其再次分配内存,因此声明可以声明多次;
而定义,程序在运行时为其变量或函数开辟内存空间,定义只能定义一次。
至于初始化,则是完成内存空间开辟,为其开辟的内存填指定的值。
三、全局变量无法赋值
全局变量是无法在定义以后赋值的,只能初始化赋值,否则会在编译阶段报错:
至于为什么,这涉及到代码编译的阶段和过程以及程序运行的阶段和过程,int a=1;
这条语句与int a;a=1
这两条语句并不能等同。前者一条语句其实是由编译器来完成的,后者两条语句的则不行,a=1
这个赋值操作是真正的运算,要放在计算机内存里去"执行"。代码的编译只涉及代码区和全局区,其中代码区是只读的,全局区只能存放数据,那个“执行”操作在编译阶段就完成不了。由于编译的时候没法赋值,所以编译器会认为这条语句的意思是int a=1;
但是int不能省略,因此最终会报错。
简单来讲就是编译阶段不进行赋值运算,只进行初始化,因此编译器认为这是一条错误语句。赋值运算要交给内存去做,所以可以在main函数中对a赋值:
另外C语言和Python不同,Python不允许修改全局变量,如果使用赋值语句,Python会在函数内部定义一个同名的局部变量。但是C语言可以修改,这就导致C语言的全局变量会造成很多的bug,所以不推荐使用全局变量。