C语言第三天02
1.数据类型
1.1C是有类型的语言
C语言的变量,必须在使用前定义,并且确定类型
C以后的语言向俩个方向发展:1.C++/Java更强调类型,对类型的检查更严格。2.JavaScript,Python,PHP不看重类型,甚至不需要事先定义
1.2类型安全
支持强类型的观点认为明确的类型有助于尽早发现程序中的简单错误
反对强类型的观点认为过于强调类型迫使程序员面对底层,实现而非事务逻辑
C语言需要类型,但是对类型的安全检查并不足够
1.3C语言的类型
1.整数
char ,short,int,long,longlong
2.浮点数
float,double,long double
3.逻辑
bool
4.指针
5.自定义类型
1.4类型有何不同
类型名称:int,long,double
输入输出时的格式化:%d,%ld,%lf
所表达的数的范围:char <short < int <float <double
内存中所占据的大小:1个字节到16个字节
内存中的表达形式:二进制数(补码),编码
1.5sizeof
是一个运算符,给出某个类型或变量在内存中所占据的字节数
sizeof(int) ,sizeof(i)
是静态运算符,它的结果在编译时刻就决定了
不要在sizeof的括号里做运算,这些运算不会做的
2.整数类型
char: 1字节(8比特)
short: 2字节
int: 取决于编译器(CPU),通常的意义是“1个字”
long: 取决于编译器(CPU),通常的意义是"1个字"
longlong: 8字节
3.整数的内部表达
计算机内部一切都是二进制
3.1二进制负数
1个字节可以表达的数:
00000000 ——————11111111(0-255)
三种方案:
1.仿照十进制,有一个特殊的标志表示负数
2.取中间的数为0,如10000000表示0,比它小的是负数,比它大的是正数
3.补码
3.2补码
考虑-1,我们希望-1+1 -> 0.如何能做到?
0 ————>00000000
1 ————>00000001
11111111 + 00000001 ————>1000000000
因为0 - 1 ————> -1 所以 -1 =
(1)00000000 - 00000001 -> 11111111
11111111被当作纯二进制看待时,是255,被当作补码看待时是-1
同理,对于-a ,其补码就是0-a, 实际是2的n次方-a,n是这种类型的位数
4.整数的范围
4.1数的范围
对于一个字节(8位),可以表达的是
00000000 - 11111111
其中
00000000 ————> 0
111111111 ~ 10000000 ————-1 ~-128
000000001 ~ 01111111 ———— 1 ~ 127
4.2整数的范围
char: 1字节:-128 ~ 127
short: 2字节: -32768 ~ 32767
int: 取决于编译器(CPU),通常的意义是“1个字”
long: 4字节
longlong: 8字节
4.3unsigned
如果一个字面量常数想要表达自己是unsigned,可以在后面加u或U
255U
用l或者L表示long(long)
unsigned的初衷并非扩展数能表示的范围,而是为了做纯二进制运算,主要是为了移位
4.4整数越界
整数是以纯二进制方式进行计算的,所以:
11111111 + 1 ————>100000000 ————> 0
01111111 + 1 ————>10000000 ————> -128
10000000 - 1 ————>01111111 ————> 127
5.整数的输入输出
5.1整数的输入输出
只有俩种形式:int或long long
%d:int
%u: unsigned
%ld: long long
%lu: unsigned long long
5.28进制和16进制
一个以0开始的数字字面量是8进制
一个以0x开始的数字字面量是16进制
%o用于8进制,%x用于16进制
8进制和16进制只是如何把数字表达为字符串,与内部如何表达数字无关
16进制很适合表达二进制数据,因为4位二进制正好是一个16进制位
8进制的一个数字正好表达3位二进制
因为早期计算机的字长是12的倍数,而非8
6.选择整数类型
1.为什么整数要有那么多种?
为了准确表达内存,做底层程序的需要
2.没有特殊需要,就选择int
现在CPU的字长普遍是32位或64位,一次内存读写就是一个int,一次计算也是一个int,选择更短的类型不会更快,甚至可能更慢
现代的编译器一般会设计内存对齐,所以更短的类型实际在内存中有可能也占据一个int的大小(虽然sizeof告诉你更小)
3.unsigned与否只是输出的不同,内部计算是一样的
7.浮点类型
7.1浮点的输入输出
类型 scanf printf
float %f %f,%e
double %lf %f,%e
7.2科学计数法
7.3输出精度
在%和f之间加上,n可以指定输出小数点后几位,这样的输出是做4舍5入的
printf("%.3f\n",-0.0049); ————>-0.005
printf("%.30f\n",-0.0049); ————>-0.00489999999998417 精度不够
printf("%.3f\n",-0.00049); ————>-0.000
8.浮点数的精度与范围
8.1超过范围的浮点数
printf输出inf表示超过范围的浮点数:+-∞
printf输出nan表示不存在的浮点数
8.2浮点运算的精度
#include<stdio.h>
int main(){
float a,b,c;
a=1.345f;
b=1.123f;
c=a + b;
if(c==2.468)
printf("相等\n");
else
printf("不相等!c=%.10f,或%f\n",c,c);
return 0;
}
结果:不相等!c=2.4679999352,或2.468000
结论:f1 == f2可能失败
fabs(f1-f2)<|e的-12次方
带小数点的字面量是double而非float
float需要用f或F后缀来表明身份。
8.3浮点数的内部表达
浮点数在计算时是由专门的硬件部件实现的
计算double和float所用的部件是一样的
8.4选择浮点类型
如果没有特殊需要,只使用double
现在CPU能直接对double做硬件运算,性能不会比float差,在64位的机器上,数据存储的速度也不比float慢
9.字符类型
char是一种整数,也是一种特殊的类型:字符。这是因为:
用单引号表示的字符字面量:'a','1'
''也是一个字符
printf和scanf里用%c来输入输出字符
9.1字符的输入输出
如何输出'1'这个字符给 char c?
scanf("%c",&c); ————> 1
scanf("%d",&i); c=i ————> 49
'1'的ASCII编码是49,所以当c==49时,它代表'1'
9.2混合输入
9.3字符计算
一个字符加一个数字得到ASCII码表中那个数之后的字符
两个字符的减,得到他们在表中的距离
9.4大小写转换
字母在ASCII表中时顺序排列的
大写字母和小写字母是分开排列的,并不在一起
‘a’-'A’可以得到两段之间的距离,于是
a+‘a’-'A’可以把一个大写字母变成小写字母而
A+‘A’-'a’可以把一个小写字母变成大写字母
10.逃逸字符
用来表达无法印出来的控制字符或特殊字符,它由一个反斜杠“\”开头,后面跟上另一个字符,这两个字符合起来,组成了一个字符
printf("请分别输入身高的英尺和英寸,"如输入\"5 7\"表示5英尺7英寸:");
11.类型转换
11.1自动类型转换
当运算符的两边出现不一致的类型时,会自动转换成较大的类型
大的意思是能表达的数的范围更大
shar —> short -> int ->long ->long
int-> float-> double
对于printf,任何小于int的类型都会被转换成int;float会转换成double
但scanf不会,要输入shord,需要%hd
11.2强制类型转换
只是从那个变量计算出了一个新的类型的值,它并不改变那个变量,无论是值还是类型都不改变
强制类型转换的优先级高于四则运算
要把一个踉跄值转换成另一个类型(通常是较小的类型),需要:
(类型)值
比如:
(int)10.2
(short)32
注意这时候的安全性,小的变量不总能表达大的量
(short32768)
12.逻辑类型
#include<stdbool.h>
之后就可以使用bool和true,false
13.逻辑运算
逻辑运算是对逻辑量的运算,结果只有0或1
逻辑量时关系运算或逻辑运算的结果
13.1优先级
13.2短路
逻辑运算是自左向右进行的,如果左边的结果已经能够决定结果了,就不会做右边的计算
a==6 && b==1
a==6 && b+=1
对于&&,左边是false时就不做右边了
对于||,左边是true时就不做右边了
14.条件运算和逗号运算
count =(count>20)?count - 10:count+10;
条件满足时的值和条件不满足时的值
翻译:if(count>20)
count = count-10
else
count = count+10
14.1优先级
条件运算符优先级高于赋值运算符,但是低于其他运算符
14.2逗号运算符
逗号用来连接两个表达式,并以其右边的表达式的值作为它的结果。逗号的优先级是所有的运算符中最低的,所以它两边的表达式会先计算;逗号的组合关系是自左向右,,所以左边的表达式会先计算,而右边的表达式的值就留下来作为逗号运算的结果
在for中使用
for(int i =0; int j =n ; i<j;i++,j–)