云课堂课程,由浙江大学翁恺老师讲授。
1.0 数据类型
C是有类型的语言
C语言的变量,必须
- 在使用前定义,并且
- 确定类型
C以后的语言向两个方向发展
- C++/Java 更强调类型,对类型的检查更严格
- JavaScript、Python、PHP不看重类型,甚至不需要事先定义类型安全
- 支持强类型的观点认为明确的类型有助于尽早发现程序中的简单错误
- 反对强类型的观点认为过于强调类型迫使程序员面对底层、实现而非事务逻辑
- 总的来说,早期语言确定类型,面向底层的语言强调类型
- C语言需要类型,但是对类型的安全检查并不足够
C语言的类型
- 整数
char、short、int、long、long long - 浮点数
float、double、long double - 逻辑
bool - 指针
- 自定义类型
类型有何不同
- 类型名称:int、long、double
- 输入输出时的格式化:%d、%ld、%lf
- 所表达的数的范围:char
sizeof
- 是一个运算符,给出某个类型或变量在内存中所占据的字节数
sizeof(int)
sizeof(i) - 是静态运算符,它的结果在编译时刻就决定了
- 不要在 sizeof 的括号里做运算,这些运算不会做的
1.1 整数类型
整数类型
整数
- char:1 字节(8 比特)
- short:2 字节
- int:取决于编译器(CPU),通常的意义是“1 个字”
- long:取决于编译器(CPU),通常的意义是“1 个字”
- long long:8 字节
整数的内部表达
二进制负数
- 1 个字节可以表达的数
00000000—11111111(0—255) - 三种方案
- 仿照十进制,有一个特殊的标志表示负数
- 取中间的数为 0,如 10000000 表示 0,比它小的是负数,比它大的是正数
- 补码
补码
- 考虑 -1,我们希望 −1+1→0,如何能做到?
0→00000000
1→00000001
11111111+00000001→100000000 - 因为 0−1→−1,所以,−1=
(1)00000000−00000001→11111111 - 11111111 被当作纯二进制看待时,是 255,被当作补码看待时是 −1
- 同理,对于 −a,其补码就是 0−a,实际是 2n−a,n 是这种类型的位数
补码的意义就是拿补码和原码可以加出一个溢出的“零”
整数的范围
数的范围
- 对于一个字节(8 位),可以表达的是
00000000−11111111 - 其中
00000000→0
11111111∼10000000→−1∼−128
00000001∼01111111→1∼127
unsigned
- 在后面加 u 或 U 表示 unsigned
- 在后面加 l 或 L 表示 long
- unsigned 的初衷并不是扩展数能表达的范围,而是为了做纯二进制运算,主要是为了移位
选择整数类型
- 为什么整数要有那么多种?
为了准确表达内存,做底层程序的需要 - 没有特殊需要,就选择 int
– 现在的 CPU 的字长普遍是 32 位或 64 位,一次内存读写就是一个 int,一次计算也是一个 int,选择更短的类型不会更快,甚至可能更慢
– 现在的编译器一般会设计内存对齐,所以更短的类型实际在内存中有可能也占据一个 int 的大小(虽然 sizeof 告诉你更小) - unsigned 与否只是输出的不同,内部计算是一样的
1.2浮点类型
浮点数的范围与精度
超出范围的浮点数
- printf 输出 inf 表示超出范围的浮点数: ±∞
- printf 输出 nan 表示不存在的浮点数
浮点运算的精度
- 带小数点的字面量是 double 而非 float
- float 需要用 f 或 F 后缀来表明身份
浮点数的内部表达
- 浮点数在计算时是由专用的硬件部件实现的
- 计算 double 和 float 所用的部件是一样的
选择浮点类型
- 如果没有特殊需要,只使用 double
- 现代 CPU 能直接对 double 做硬件运算,性能不会比 float 差,在 64 位的机器上,数据存储也不会比 float 慢
1.3 逻辑类型
bool
#include <stdbool.h>
逻辑运算
短路
- 逻辑运算是自左向右进行的,如果左边的结果已经可以决定结果了,就不会做右边的计算
- 不要把赋值,包括复合赋值组合进表达式
1.4 类型转换
自动类型转换
- 当运算符的两边出现不一致的类型时,会自动转换成较大的类型
– 大的意思是能表达的数的范围更大
– char → short → int → long → long long
– int → float → double - 对于 printf 来说,任何小于 int 的类型会被转换为 int;float 会被转换为 double
- 但是 scanf 不会,要输入 short,需要 %hd
强制类型转换
- 要把一个量强制转换为另一种类型(通常是较小的类型),需要:
(类型)值; - 强制类型转换的优先级高于四则运算
条件和逗号运算
优先级
- 条件运算符的优先级高于赋值运算符,但是低于其他运算符
- 条件运算符是自右向左结合的
逗号运算
- 在 for 中使用