一. 基本类型
1. 整型
short(2个字节),int(4个字节),long(4个字节)
2. 字符型
char(1个字节)
这里就以char来和大家聊一聊范围问题,以及超出范围问题,其他可以参照char类型
unsigned char : 0~255, 因为1个字节就是8bit,也就是8个二进制位,最小就是 0000 0000 = 0,最大就是 1111 1111 = - 1 = 255
signed char : -128~127,因为最高位"1"表示负数,最高位"0"表示正数,最高位不参与计算,所以最大为 0 111 1111 = -1 = 127,最小理论上是 1 111 1111 = -(-1)= -127,但是我们可以看一下,-128原码是 1 1000 0000,反码是 1 0111 1111,补码就是 1 1000 0000,因为char只能存储8位,所以把最高位去掉,就是 1000 0000,所以在char中规定 1000 0000代表-128
如果一个数超出了char类型该如何存储呢?这里给大家解答一下
比如char num1 = 300,chari num2 = -228,显然num1和num2都超出了存储范围,那它们会输出多少呢?
如果是正数,那么就先将该数的二进制写出来,然后保留低8位将其输出。比如,300的二进制是 1 0010 1100,保留低8位输出最后结果就是44,其他的也是按照这个方法一样出结果。
如果是负数,首先写出其二进制,然后对其取反码,然后补码,保留低8位输出即可。比如,-228的二进制就是 1 1110 0100,反码就是 1 0001 1011,补码就是 1 0001 1100,然后保留低8位输出就是 28,这里同样最高位代表符号,不参与计算
3. 实型
float(4个字节),double(8个字节)
无论是float还是double,默认都是小数点后6位,如果想手动保留几位可以在格式化输出前写。
#include<cstdio>
int main(){
float x = 3.14f;
double y = 2.56;
float e = 2.723e+10f;
// 输出2位小数
printf("x=%.2f\n",x);
// 输出3位小数
printf("y=%.3lf\n",y);
printf("e=%e\n",e);
}
4. bool类型
bool类型只能存储两个值,0或1,就算存储了其他的数值,在最后输出的时候如果是非0就会输出1,是0就会输出0。
5. 常量
常量就是在使用过程中直接可以使用,不需要我们再额外去定义的量,我们又叫它宏定义。举个简单的例子,我们在计算使用到π时候,使用了很多次π,如果想修改一下π的值,那么代码里面每一个π都需要修改,但是如果我们使用了宏定义,只需要修改宏定义里面的π即可,方便了很多。
但是呢,这里有一个小小的坑需要大家注意一下,宏定义从某种意义上来说只是简单的替代,所以在遇到了算数的时候最好加上小括号()来提高一下优先级,不然容易出错,给大家举个例子就知道了。
在这段代码中,执行顺序大家普遍理解的可能是 1 + 2*20 + 10 = 51,可是最后的答案是32,这就是问题所在,其实这段代码是这样的, 1 + 1 + 1*20 +10 =32,因为那个宏定义TWO就是直接替换下来了,如果想要达到第一种想过,可以在宏定义加上小括号提高计算的优先级
6. 变量
变量的命名 :<存储类型> <数据类型> <变量名>
这里我就来重点讲解一下存储类型这个东西,我相信其他两个大家都没什么问题。
6.1 auto(默认的)
auto只能在某个范围内使用,如果超出了那个范围就没用了,这里所指的范围可以是函数,可以是复合语句
大家可以看到,这里的a变量是在if条件语句里面定义的,第二个printf不在if复合语句里面,所以第二个printf里面的a报错了
6.2 register
register又称寄存器型,它是把变量放到寄存器中,加快程序运行的速度,但是请不要什么都放到寄存器中,因为电脑的cpu寄存器有限,如果什么都放到寄存器反而会得不偿失,降低运行速度。同时,因为放在了寄存器中,所以register变量不能用"&"来获取它的地址。
6.3 static
static:静态的,可以在函数体内,也可以在函数体外,如果一个变量被函数体修饰,那么它有以下特点:
1: 在内存中以固定地址存放,而不是以堆栈存放
2:只要程序没有结束,那么这个变量就不会被销毁,继续沿用上一次存储的值
这里给大家举个例子看看就懂了
大家可以看到这个while循环中,变量a是没有用static修饰的,所以它使用了一次之后再次进入循环体就是新的,所以大家看到的都是a=1
但是在这段代码中的变量a前面添加了一个static修饰,那么在这个while循环结束之前,变量a都不会被销毁,会一直存在
6.4 extern
当变量在函数体外部声明,如果在另外一个文件想要拿到这个变量的话我们可以使用extern。话不多说,直接上案例
这里的age和num我们没有赋值,但是可以使用,是因为拿了另外文件的,同时这里注意一下,如果一个变量被static修饰的话,那么这个变量不能被别人引用。当然,如果出现了个别extern不能使用的情况可能和编译器有关等等