数据类型
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 < short < int < float < double
- 内存中所占据的大小:1个字节到16个字节
- 内存中的表达形式:二进制数(补码)、编码
sizeof
- 是一个运算符,给出某个类型或变量在内存中所占据 的字节数|
- sizeof(int)
- sizeof(i)
- 是静态运算符,它的结果在编译时刻就决定了
- 不要在sizeof的括号里做运算,这些运算不会做的
整数
- char:1字节(8比特) •
- short:2字节 •
- int:取决于编译器(CPU),通常的意义是“1个字”
- long:取决于编译器(CPU),通常的意义是“1个字”
- long long:8字节
二进制负数
1个字节可以表达的数:
- 00000000 — 11111111 (0-255)
三种方案:
- 仿照十进制,有一个特殊的标志表示负数
- 取中间的数为0,如1000000表示0,比它小的是 负数,比它大的是正数
- 补码
补码
考虑-1,我们希望-1+ 1 —> 0。如何能做到?
- O—> 00000000 •
- 1—> 00000001 • 11111111 + 00000001 —> 100000000
因为0-1 —>-1,所以,-1 =
- (1)00000000,- 00000001 —>11111111
- 11111111被当作纯二进制看待时,是255,被当作补码看待时是 •同理,对于-a,其补码就是0-a,实际是2"-a,n是这种类型的位数
- 同理,对于-a,其补码就是0-a,实际是2"-a,n是这种类型的位数
补码的意义就是拿补码和原码可以出一个溢出的“零”
数的范围
对于一个字节(8位),可以表达的是:
- 0000000- 11111111
其中
- 00000000 —>0
- 11111111~ 10000000 —>-1~-128
- 00000001~ 01111111—> 1~ 127
整数的格式化
整数的输入输出
- 只有两种形式:int或long long
- %d:int •
- %u:unsigned
- %ld:long long
- %lu:unsigned long long
8进制和16进制
- 一个以0开始的数字字面量是8进制
- 一个以0x开始的数字字面量是16进制
- %o用于8进制,%x用于16进制 -
- 8进制和16进制只是如何把数字表达为字符串,与内部如何表达数字无关
- 16进制很适合表达二进制数据,因为4位二进制正好 是一个16进制位
8进制的一位数字正好表达3位二进制
- 因为早期计算机的字长是12的倍数,而非8
选择整数的类型
为什么整数要有那么多种?
- 为了准确表达内存,做底层程序的需要
没有特殊需要,就选择int
- 现在的CPU的字长普遍是32位或64位,一次内存读写就是 一个int,一次计算也是一个int,选择更短的类型不会更 快,甚至可能更慢
- 现代的编译器一般会设计内存对齐,所以更短的类型实 际在内存中有可能也占据一个int的大小(虽然sizeof告诉 你更小)
- unsigned与否只是输出的不同,内部计算是一样的
浮点类型
浮点的输入输出
科学计数法
浮点数的范围和精度
输出精度
- 在%和f之间加上.n可以指定输出小数点后几位,这样 的输出是做4舍5人的 •
- printf("%.3fin",-0.0049);
- printf("%.30fn",-0.0049);
- printf("%.3fin",-0.00049);
超过范围的浮点数
- printf输出inf表示超过范围的浮点数:±0
- printf输出nan表示不存在的浮点数
浮点运算的精度
浮点数的内部表达
选择浮点类型
- 如果没有特殊需要,只使用double
- 现代CPU能直接对double做硬件运算,性能不会比 float差,在64位的机器上,数据存储的速度也不比 float慢
字符类型
char是一种整数,也是一种特殊的类型:字符。这是 因为:
- 用单引号表示的字符字面量:'a','1'
- ‘ ’也是一个字符
- printf和scanf里用%c来输入输出字符
字符的输入输出
如何输入'1'这个字符给char c?
- scanf("%c",&c);—>1
- scanf("%d",&i); c=i;—->49
- ‘1'的ASCII编码是49,所以当c==49时,它代表‘1’
大小写转换
- 字母在ASCII表中是顺序排列的
- 大写字母和小写字母是分开排列的,并不在一起
'a’-'A’可以得到两段之间的距离,于是
- a+'a-'A”可以把一个大写字母变成小写字母,而
- a+'A-'a'可以把| 个小写字母变成大写字母
逃逸字符
- 用来表达无法印出来的控制字符或特殊字 符,它由一个反斜杠“\”开头,后面跟上另 一个字符,这两个字符合起来,组成了一 个字符
printf("请分别输入身高的英尺和英寸,” "如输入\"5 7\"表示5英尺7英寸:");
制表位
- 每行的固定位置
- 一个\t使得输出从下一个制表位开始
- 用\t才能使得上下两行对齐
类型转换
自动类型转换
当运算符的两边出现不一致的类型时,会自动转换成 较大的类型
- 大的意思是能表达的数的范围更大
- char—> short —>int —> long —> long long
- int —> float —> double
- 对于printf,任何小于int的类型会被转换成int;float会 被转换成double
- 但是scanf不会,要输入short,需要%hd
强制类型转换
要把一个量强制转换成另一个类型(通常是较小的类 型),需要:
- (类型)值
比如:
- (int)10.2
- (short)32
注意这时候的安全性,小的变量不总能表达大的量
- (short)32768
只是从那个变量计算出了一个新的类型 的值,它并不改变那不变量,无论是值 还是类型都不改变
逻辑类型
bool
- include <stdbool.h>
- 之后就可以使用bool和true、false
逻辑运算
- 逻辑运算是对逻辑量进行的运算,结果只 有0或1
- 逻辑量是关系运算或逻辑运算的结果
注意
优先级
短路
- 逻辑运算是自左向右进行的,如果左边的结果已经能 够决定结果了,就不会做右边的计算
- a==6 && b==1
- a==6&& b+=1
- 对于&&,左边是false时就不做右边了
- 对于l,左边是true时就不做右边了
不要把赋值,包括复合赋值组合进表达式!
条件运算符与逗号运算
条件运算符
- count =(count>20)?count -10 :count +10;
- 条件、条件满足时的值和条件不满足时的值
if ( count >20)
count= count-10;
else
count = count+10;
优先级
条件运算符的优先级高于赋值运算符,但是低于其他运算符
- m<n? x : a+5
- a++>= 1 && b--> 2 ? a : b
- x=3 * a > 5? 5 : 20
嵌套条件表达式
- count =(count> 20)?(cout < 50)? count - 10:count - 5 :(count < 10)? count + 10: count + 5;
- 条件运算符是自右向左结合的 •x<x?×+w:x<y?×:Y
我们不希望你使用嵌套的条件表达式
逗号运算符
- 逗号用来连接两个表达式,并以其右边的 表达式的值作为它的结果。逗号的优先级 是所有的运算符中最低的,所以它两边的 表达式会先计算;逗号的组合关系是自左 向右,所以左边的表达式会先计算,而右 边的表达式的值就留下来作为逗号运算的 结果。
- 在for中使用, for (i=0,j=10;i<j;i++,j--)…....