主要说的是C中的一些数据类型的知识点,所有测试和假设以32位机器为例:
- 关于浮点数
- 在精度上,float默认是可以精确到小数点后6位,第七位就开始混乱
- 而double可以精确到小数点后16位,从第17位开始混乱
- 在printf中打印的时候,不论是float还是double都使用”%f”来打印,”%d”是用来打印数字的,这一点需要注意
- 浮点数在内存中的存储方式,以科学计数法的方式存储,把小数部分和正数部分分开存储
- 关于有符号和无符号
- 符号就是正负号,有符号就是区分正负数,无符号就不区分正负数,全是正数,最小数从0开始以此累计。
- 首先明白概念,如果要表示正负数,那么最高位就是符号位,符号位1代表负数,0代表整数
- 那么把这个概念放在各种数据类型中,不论他们的位数有多长,最高位现在不表示数据,而是一个单独的符号位,有0和1两种
- 那么有符号数的范围和表示形式就出来了,拿一个char来说 第八位是符号位,那么最大的正数就是0111,1111 = 127,最小的负数就是1111,1111 = -128,就是酱紫,其他数据类型一样以此类推,只用变换最高位即可。
- 有符号数由于存在正负号判断所以效率比无符号数要低,如果允许优先使用无符号数。
- 根据规律,可以得出公式
- 有符号数最大正数 = 取反(有符号数最小负数+1),
- 有符号数最小负数 = 取反(有符号数最大正数-1)
- 无符号数最小 = 0,最大值 = 同类型有符号数最大正数 + 取反(有符号数最小负数)
- 注意浮点数据类型,没有无符号类型这个概念
- 关于结构体
- 结构体和和函数,全局变量同级,定义在函数之外
- 结构体是一种新的组合数据类型,定义结构体并不消耗内存,之后创建结构体变量的时候才会消耗内存
- 结构体的定义和函数的声明以定义有相似之处
- 结构体的定义格式:struct 结构体类型 { 结构体字段,…};
- 结构体变量的定义:struct 结构体类型 结构体变量1,…;
- 还可以直接在结构体定义的时候,直接定义结构体变量:struct 结构体类型 { 结构体字段,…} 结构体变量1,…;,不过这种方式的结构体类型只能临时使用一次,以后要想再使用这种结构体类型还需要重新定义
- 结构体变量初始化,假设有结构体
struct Student {int age,char sex}
,则可以定义结构体变量struct Student sanmao = {21,'F'};
这种定义时初始化,也可以先定义变量,然后再进行初始化struct Student sanmao; sanmao = {21,'F'};
- 结构体变量的赋值:结构体变量名.结构体字段 = 字段值;
- 如果定义了结构体变量而没有进行初始化,结构体中各个字段的值是随机的
- 关于共用体
- 共用体的定义:被多个字段共用的数据类型
- 共用体的类型定义,变量定义,以及初始化都和结构体一样,只不过把struct改成了union
- 共用体和结构体的区别:
- 共用体中的每个字段每次只能使用其中一个,而结构体中的所有字段够可以使用
- 共用体只容的下一个字段在共用体变量中,一旦初始化了共用体其中一个字段,如果再尝试初始化另外一个字段,则先前字段的值会被覆盖
- 共用体变量所占用的内存空间大小取决于所有字段类型中占用空间最大的类型,结构体的内存空间占用在不考虑对齐的情况下,取决于所有字段占用空间之和
- 共用体其中存的值,按照其中各个字段的定义,可以有不同的表现
- 共用体其中只有一个值,被好几个不同类型或者不同名称的数据共用
- 共用体常用来定义这种情况下的数据类型:一个xxx可能有好几种类型或者选项,但是它在同一时间只会使用其中的一种
- 关于枚举
- 枚举是一种数据类型
- 枚举的定义:
enum week {MON,TUE,WEN,THU,FRI,SAT,SUN};
- 枚举变量的定义:
enum week today;
- 甚至可以参照结构体和共用体的方式,在定义枚举类型的时候直接定义变量
enum week {MON,TUE,WEN,THU,FRI,SAT,SUN} today;
- 枚举变量的初始化,可以在定义的时候初始化
enum week today = TUE;
,也可以在定义之后进行初始化enum week today; today = TUE;
- 枚举中的每一个枚举项会默认从0开始依次初始化,而且可以直接使用枚举项的值赋值给枚举变量,例如
enum week today = 1;
的效果等同于4中的初始化 - 可以手动指定每个枚举项的值,如果只指定了某一个枚举项的值,那么该枚举项以后的值就会按照当前枚举项的值依次递增,例如:
enum.TUE = 9;
,则WEN,THU,FRI,SAT,SUN的值依次为10,11,12,13,14
- 关于void
- void不是没有类型,相反是一种确切的类型,这个类型代表任意类型,有点不确定类型的概念
- void可以用在函数的参数,返回值等任何可以表示数据类型的位置上
- 被void修饰的地方可以:
- 不需要传递参数,因为参数类型不确定
- 不需要返回值,因为返回值类型不确定
- 在malloc分配类型的时候就会使用到void 类型,表示分配的内存空间适用的数据类型不确定,例如void *表示该指针指向的数据类型不确定
- register与extern
- register的变量,会尽量放在寄存器中来提高读取速度,但是CPU不能百分百保证
- 由于寄存器数量的限制,register类型的变量不能定义太多
- register在数据类型上有限制,例如不能用在double上,因为寄存器不支持
- 一般在需要反复使用同一个变量的情况下,例如内核或者启动代码中,才会使用register来定义变量
- 如果在全局变量之前有extern关键字,表示这个全局变量使用的是同程序中其他文件中的同名全局变量