变量的声明,定义和初始化
众所周知,我们要使用一个变量,就需要计算机把变量做出来。也就是说,变量在哪里存储,如何存储等,这样的一些信息,需要我们说明。这就是变量的定义。在变量定义时,如果我们给它赋值,这就叫变量的初始化。例如:
int a = 10; // 这是初始化
int b;
b = 10 // 这不是初始化!
我们要明确两个概念:
1.变量的声明:告诉编译器有这么一个变量。
2.变量的定义:告诉编译器如何创建变量。
在c语言中,变量的定义实际上要两个关键词修饰,一个说明变量存在哪──存储类,一个说明变量的数据类型。接下来由表格和代码解释:
auto | 局部变量,变量被存在栈上 |
static | 变量被存在静态存储区 |
register | 变量可能被存在寄存器中,读写速度更快 |
extern | 只是声明有一个外部变量,不是定义 |
上面这段代码中,两个变量定义的方式是一样的,也就是说,auto可以省略。
上面这段代码中,static修饰的变量a,b都存储在静态存储区,若不主动初始化,它们也会被默认初始化为0,而变量c可能会被存到寄存器中,存到寄存器中的变量读写速度更快,但不可以取地址。静态变量的引入是为了调整变量的生命周期。
//以下为A.c文件中
int a = 0;
//以下为B.c文件中
extern int a;
int main()
{
a = 10;
return 0;
}
上面这段代码中,变量a在文件A中定义,而文件B想要使用,那么就需要extern声明。
变量的作用域和生命周期
变量分为局部变量和全局变量两种。作用域是变量能在哪里被使用,生命周期是变量什么时候创建,什么时候销毁。
1.局部变量
局部变量在函数内部定义,局部变量在代码执行到函数内部的时候创建,离开函数时销毁,局部变量不可以在函数外使用。
2.全局变量
全局变量在函数外部定义,会被默认初始化为0,全局变量在整个程序的运行过程中都可用,在任何函数内都可以使用。
3.静态变量
静态变量定义的地方决定了静态变量的作用域,也就是静态变量分为静态(全局/局部)变量但其生命周期为整个程序。
数据存储的细节
1.所占内存大小
关于计算机中数据的存储,我们首先要知道计算机中的数据是1和0组成的二进制序列。
计算机中存储的最小单元是:比特 bit(s) 也就是一个二进制位,可以表示0或1,一个字节 byte(s) 等于八个比特
1byte = 8 bits, 1kb = 1024bytes, 1MB = 1024KB 1GB= 1024MB
那么我们一个int类型的变量占了多大的空间呢?可以使用sizeof()查看。
像如上代码的方式,其中sizeof()内的int可以替换成其他类型名,程序会打印出这种类型所占的内存,单位:字节。
数据类型所占的内存可能会根据操作系统,编译器的不同而不同,想要知道占了多大还是得自己测试一下看看。
2.整型,字符类型存储方式
这里介绍的存储方式,不过是说每个比特的数据都用来表示什么,整数和字符类型的存储方式在形式上一样,都是整数,只不过表达字符的整数被按一定的规则显示成字符。
使用以上代码就能明白各种字符与整数之间的对应关系,具体请搜索ASCII码表
此外,由于一些字符键盘上没有,C语言使用转义字符来表达
我们以整型int为例,它具有 4 bytes = 32 bits,如果不使用unsigned关键词来修饰,那么最高位为符号位,表示正负,其他位构成二进制数,关于二进制和十进制的转换请自行搜索。
但单单是转换成二进制就万事大吉了吗?不,为了使加减法统一进行计算,我们引入了原码,反码,补码的概念
1.对于正整型,原码反码补码相同。
2.对于负整型,反码是原码除了符号位按位取反,补码是反码加1。
我们可以用位运算将整数以二进制形式打印出来查看细节。