目录
我们都知道 程序 = 数据结构 + 算法,而学习数据结构前,一定要把数据类型啃透,负责就可能出现各种段错误或者溢出的错误。而对于初学者来说,学习数据类型的基本知识是容易的,但是有些底层知识与比较偏的知识,我认为也是需要掌握的。
一、c语言的数据类型
1.基本类型
数据在计算机底层的存储
要注意的东西来了
第二个小知识
浮点常量小知识
运算符
细碎的知识
正文
一、c语言的数据类型
1.基本类型
C语言为我们定义好的类型,我们直接拿来用。
主要针对:
数:整数、浮点
1.1整型
char/unsigned char : 1byte = 8bits
char: -128 ~127
unsigned char: 0 ~ 255
short/unsigned short: 2 bytes
int/unsigned int: 4 bytes
long / unsigned long: 8bytess
在ubuntu18.04 【在不同的编译器下,字节长度不一样】
sizeof(short) = 2;
sizeof(int) = 4;
sizeof(long) = 8;
1.2 浮点型
float :单精度浮点数 sizeof(float) = 4
double:双精度浮点数 sizeof(double) = 8
long double 长双精度浮点数 sizeof(long double) = 12(>=10)
C语言中,整数默认的类型是int,小数默认的是double类型。
typeof(1) = 4
typeof(1.0) = 8
2.构造类型:自定义的类型
C语言中,允许我们程序员自定义类型。
2.1数组
int a[4];// typeof(a) = int[4]
int b[10];//typeof(b) = int[10]
typeof(a) != typeof(b)
typeof(a[0]) : int
typeof(b[0]) : int
所以:typeof(a[0]) = typeof(b[0])
3.void类型
在c语言中,void出现在三个地方
(1)void当函数的参数,表示该函数无参。
int func(void)
{
}
(2)void当函数的返回值类型,表示该函数无返回值。
void func(int a)
{
}
调用:int m = func(6);
func(6);
(3)void* 表示一个通用指针,可以指向任何数据类型。
数据在计算机底层的存储
整数在计算机中是如何存放的呢?
是通过二进制的补码形式存放的。
补码:正数的补码是其本身 负数:是其绝对值的原码取反加1
要注意的东西来了
举个栗子:char类型是1字节,范围是 “-128~127”
而 unsigned char类型也是1字节,但范围是“0~255”
那同学们有没有思考过,同一个类型,有符号与无符号的范围这么规定,具体原因是什么呢?
其原因就是正数与负数在计算机中的存储形式了
比如一个1字节,也就是8bit的负数“-1“ 它的存储形式为 “1111 1111”
而一个1字节,8bit的正数“1”,它的存储形式也为“1111 1111”
其规律就是一个n字节的存储类型,他的“-x”与“2^n-x”在计算机里的存储形式是一样的
所以char类型“128~255”分别与unsigned char类型“-128~255”在计算机里的二进制存储形式是一样的,所以有符号与无符号将这两类分开,就不会产生歧义。
在CPU底层是没有符号位概念的,都是数值位,都参与运算,至于这个数是整数还是负数,就得看编译器的词义了,意思是说,你把这个数当做是一个有符号的数,还是一个无符号的数。
第二个小知识
C语言允许不同类型的整型相互赋值
有人提出,长度不一样,如何赋值呢?
标准C建议如下:
(1)长 - 》短
低字节直接拷贝,高字节直接丢弃。
(2)短-》长
低字节直接拷贝,高位补什么呢?
if 短的是有符号数,高位就全部补符号位。
if 短的是无符号数,高位就补0.
下面说一个快捷计算方法:
1.对一个数的二进制取反<==>这么多位“1”减这个数
如一个数的二进制为“0111 1001”,取反为“1000 0110”,也可以用“1111 1111”减“0111 1001”一样可以得到这个数,二进制下也许看不出这个方法的快捷,但在十进制下就完全不一样了
又比如,我们要对112这个8bit的数取反,正常方法要先转换为二进制再取反,得到去饭店二进制后再转成十进制,但是真的上面这个快捷方法后,我们就能直接计算。我们知道8bit全1为255,所以我们只需要用255-112,就能得出112取反的十进制为143了。怎么样,是不是很简单。
同样,有些计算中,如计算负数的补码:原码取反加1,就可以直接使用上面的方法,取反是2^n-1-x,那取反加一不就是2^n-x吗。
浮点常量小知识
由整数部分,小数点,小数部分组成,一个e/E,一个可以带符号的整型指数和一个表示类型(e/E表示科学计数法,想必大家在计算机上都见过)
而有一个需要注意的地方:字母e/E前面必须有数字;后面必须为整数(正整数、负整数)
(这是为什么呢?也许你觉得字母e/E前面的1可以省略,但是请联系字符定义,第一位不可以是数字,这样就能规避歧义)
运算符
我们再讲一些运算符的小知识吧😁
运算符的结合性:决定先算哪个操作数的问题
运算符的优先级大家应该都知道
最后一个逗号运算符一个见得少,单独说一下。
逗号表达式形式:
表达式1,表达式2,表达式3....表达式n
求值顺序:
先求表达式1的值,然后再求表达式2的值。
再求表达式3的值,。。。整个逗号表达式的值,就是表达式n的值。
细碎的知识
1、在c语言中,会自动向高精度类型转型。
2、逻辑表达式的值:
逻辑真 1(非0)
逻辑假 0
3、C语言运算符是惰性运算
(1) a&&b&&c
只有a为真时,才需要判断b的值;
只有当a和b都为真时,才需要判断c的值。
(2)a||b||c
只要a为真,就不必判断b和c的值;
只要a为假,才需要判断b的值;
只要a和b都为假,才需要判断c的值。
总而言之,如果事先知道表达式的值,那么后面的运算符表达式就不需要执行啦,因为没有必要。
4、‘<<’按位左移
a << n位: 把a按bit位整体左移n位。
1.高位左移后,舍弃,低位补0;
2.如果左移舍弃的高位全部为0,那么左移n位,就表示在原值乘以2的n次方。
5、>> 按位右移
x >> n: 把x按bit位整体右移n位。
低位右移后,舍弃;那么高位补什么呢?
对于无符号数,高位全部补0;
对于有符号数,高位全部补符号位。