@TOC
6.1数据类型
6.1.1数据类型:C语言有哪些是基础数据类型,sizeof可以做什么
C有类型的语言 C语言的变量,必须: 在使用前定义,并且 确定类型 C以后的语言向两个方向发展: C++/java更强调类型,对类型的检测更严格 javaScript,Python,PHP不看重类型,甚至不需要事先定义 类型安全 支持强类型的观点认为明确的类型有助于尽早发现程序中的简单错误 反对强类型的观点认为过于强调类型迫使程序员面对底层实现,而非事务逻辑 总的来说,早期语言强调类型,面向底层的语言强调类型 C语言需要类型,但是对类型的安全检查并不足够 C语言的类型 整数 char short int long longlong 浮点数 float double longdouble 逻辑 bool 指针 自定义类型 类型有何不同 类型名称:int long double 输入输出时的格式化:%d,%ld,%lf 所表达的数的范围:char<short<int<float<double 内存中所占据的大小:1个字节到16个字节 内存中的表达形式:二进制数(补码),编码 sizeof 是一个运算符,给出某个类型或变量在内存中所占据的字节数 sizeof(int) sizeof(i) 是静态运算符,它的结果在编译时刻就决定了 不要在sizeof的括号里做运算,这些运算不会做的
6.1.2数据类型:除了int,还有多少整数类型
整数 char:1字节(8比特) short:2字节 int:取决于编译器(CPU),通常的意义是“1个字” long:取决于编译器(CPU),通常的意义是“1个字” long long:8字节
6.1.3整数的内部表达式:整数是如何表达的,尤其是负数如何表达的
整数的内部表达 计算机内部一切都是二进制 18--->00010010 0--->00000000 -18--->? 如何表示负数 十进制用“-”来表示负数,在做计算的时候 加减是做相反的运算 乘除时当做正数,计算完毕后对结果的符号取反 二进制负数 1个字节可以表达的数 00000000----11111111(0-255) 三种方案: 1.仿照十进制,有一个特殊的标志表示负数 2.取中间的数为零,如100000000表示0,比它小的是负数,比它大的是正数 3.补码 补码 考虑负一,我们希望负一加一等于零。如何能做到? 0--->0000 0000 1--->0000 0001 11111111+00000001=100000000 因为0-1--->-1所以,-1= (1)00000000-00000000--->11111111 11111111被当做纯二进制看待时,是255,被当做补码看待时是-1 同理,对于-a,其补码就是0-a,实际是2的n次方-a,n是这种类型的位数
6.1.4整数的范围:如何推断整数类型所能表达的范围,越界了会咋样
数的范围
对于一个字节(8位),可以表达的是:00000000-11111111
其中
00000000--->0
1111111110000000--->-1 ~ -128
0000000101111111--->127
整数的范围
char:1个字节 -128127
short:2字节-3276832767
int:取决于编译器,通常的意义是“1个字”
long 4个字节
long long 8个字节
unsigned
在整型类型加上unsigned使得它们无符号的整数
内部的二进制表达没变,变的是如何看待它们
如何输出
11111111
对于char,是负一
对于unsigned是255
如果一个字面量常数想要表达自己是unsigned,可以后面加上u
255U
用l或L表示long(long)
unsigned的初衷并非扩展数能表达的范围,而是为了做纯二进制运算,主要是为了移位
整数越界
整数是以纯二进制的方式运算的:
11111111+1--->100000000--->0
01111111+1--->10000000--->-128
10000000-1--->01111111--->127
6.1.5整数的格式化:如何格式化输入输出整数,如何处理8进制和16进制
整数的输入输出 只有两种形式int 或 long long %d: int %u: unsigned %ld: long long %lu: unsigned long 8进制和16进制 一个以0开头的数字字面量是8进制 一个以0x开头的数字字面量是16进制 %o用于八进制%x用于16进制 8进制和16进制只是如何把数字表达为字符串,与内部如何表达数字无关
6.1.6选择整数类型:没有什么特殊需求只用int就好了
选择整数类型 为什么整数要有那么多种? 为了表达内存,做底层程序的需要 没有特殊需要就选择int 现在的cpu的字长普遍是32位或64位,一次内存的读写就是一个int,一次运算也是int,选择更短的类型不会更快,有可能会更慢 unsigned与否只是输出的不同,内部的计算是一样的
6.1.7浮点类型:double 和float,它们是什么,如何输入输出
浮点类型
| 类型 | 字长 | 范围 | 有效数字 |
|---|---|---|---|
| float | 32 | +-(1.20*100,+-inf,,nan) | 7 |
| double | 64 | +-(2.2*100,+-inf,nan)15 |
浮点的输入输出
| 类型 | scanf | printf |
|---|---|---|
| float | %f | %f %e |
| double | %lf | %lf %e |
科学计数法 -5.6e+16表示负5.6乘10的十六次方 可以用E或e 输出精度 在%和f之间加上.n可以指定输出小数点的后几位,这样的输出做的是四舍五入的 printf("%.3f\n",-0.0049);
6.1.8浮点的范围与精度:浮点数到底能表达哪些数
超过范围的浮点数 printf输出int表示超过范围的浮点数:+_无穷 printf输出nan表示不存在的浮点数 浮点运算的精度
#include<stdio.h>
int main()
{
float a,b,c;
a=1.345f;
b=2.345f;
c=a+b;
printf("%.2f\n",a);
printf("%f\n",b);
printf("%f\n",c);
}
带小数点的字面量是double,而非float, float需要用f或F后缀来表明身份 选择浮点类型 如果没有特殊需求,只能使用double 现代的cpu能直接对double做double硬件运算,性能不会比float差,在64位处理器,数据存储的速度也不会比float差。
6.1.9字符类型char是整数也是字符
字符类型 char是一种整数,也是一种特殊的类型:字符。这是因为: 用单引号表示的字符字面量:‘a’,'1' ''也是一个字符 printf和scanf里用%c来输入输出字符 字符的输入输出 如何输入‘1’这个字符给char c? scanf("%%c",&c);-->1 scanf("%d",&c);c=i;--->49 '1'的ASCLL编码是49,所以当c==49时,它代表‘1’ printf(“%i %c\n”,c,c); 字符计算
char c = 'A';
c++;
printf("%c\n",c);
int i='Z'-'A';
printf("%d\n",i);
一个字符加一个数字得到ASCLL码表中那个数之后的字符 两个字符的减,得到它们在表中的距离 大小写转换 字母在ASCLL表中是顺序排列的 大写字母和小写字母是分开排列的,并不在一起 ‘a’-‘A’可以得到两段之间的距离,于是 a+‘a’-‘A’可以把一个大写字母变成小写字母,而 a+‘A’-‘a’可以把一个小写字母变成大写字母
6.1.10逃逸字符:反斜杠开头的字符是特殊的控制字符
逃逸字符 用来表达无法印出来的控制字符或特殊字符,它它由一个反斜杠“\”开头,后面跟上另一个字符,这两个字符合起来,组成了一个字符 printf("请分别输入身高的英尺和英寸,"“如输入"5 7"表示5英尺7英寸:“); 逃逸字符
| 字符 | 意义 | 字符 | 意义 |
|---|---|---|---|
| \b | 回退一格 | " | 双引号 |
| \t | 到下一个表格位 | ' | 单引号 |
| \n | 换行 | \\ | 反斜杠本身 |
| \r | 回车 |
回车换行 源自打字机的动作 制表位 每行的固定位置 一个\t使得输出从下一个制表位开始 用\t才能使得上下两行对齐
6.1.11类型转换如何在不同类型之间做转换
自动类型转换 当运算符的两边出现不一致的类型时,会自动转换成较大的类型 大的意思是能表达的数的范围更大 char-->short-->int-->long-->long long int-->float-->double 对于printf,任何小于int 的类型会被转换成int;float会被转换成double 但是scanf不会,要输入short,需要%hd 强制类型转换 要把一个量强制转换成另一个类型(通常是较小的类型),需要: (类型)值 比如: (int)10.2 (short)32 注意这时候的安全性,小的变量不总能表达大的量 (short)32768
- 只是从那个量计算出了一个新的类型的值,它并不改变那个变量,无论是值还是类型都不改变 强制类型转换的优先级高于四则运算
6.2其他运算:逻辑,条件,逗号
6.2.1逻辑类型:表示关系运算和逻辑运算的结果的量
bool #include<stdio.h> 之后就可以使用bool和true,false bool的运算 bool实际上还是以int的手段实现的,所以可以当做int来计算 也只能当做int来输入输出
6.2.2逻辑运算:对逻辑量进行与,或,非,运算
逻辑运算是对逻辑量进行的运算,结果只有0或1 逻辑量是关系运算或逻辑运算的结果
| 运算符 | 描述 | 示例 | 结果 |
|---|---|---|---|
| ! | 逻辑非 | !a | 如果a是true结果就是false,如果a是false结果就是true |
| && | 逻辑与 | a && b | 如果a和b都是true,结果就是true;否则就是false |
| || | 逻辑或 | a||b | 如果a和b有一个是true,结果为true;两个都是false,结果为true |
try 如果要表达数学中的区间,如:x属于(4,6)或x属于[4,6],应该如何写c的表达式? 正确答案:x>4&&x<6 如何判断一个字符c是否是大写字母? c>=‘A’&&c<='Z' 优先级 !>&&>||
| 优先级 | 运算符 | 结合性 | |
|---|---|---|---|
| 1 | () | 从左到右 | |
| 2 | 1 + - ++ -- | 从右到左(单目的+和-) | |
| 3 | * / % | 从左到右 | |
| 4 | + - | 从左到右 | |
| 5 | < <= > >= | 从左到右 | |
| 6 | == != | 从左到右 | |
| 7 | && | 从左到右 | |
| 8 | || | 从左到右 | |
| 9 | = += -= *= /= %= | 从右到左 |
短路 逻辑运算是自左向右进行的,如果左边的结果已经能够决定结果了,就不会做右边的计算 a==6 && b==1 a==6 && b+=1 对于&&,左边是false时就不会做右边了 对于||,左边是true时就不会做右边的了
6.2.3条件运算与逗号运算
条件运算 count=(counr>20)?count-10:count+10; 条件,条件满足时的值和条件不满足的值 等价于:
if(count>20)
count = count-10;
else
count = count+10;
优先级 条件运算符的优先级高于赋值运算符,但是低于其他运算符 尽量不要用嵌套的条件表达式 逗号运算 逗号用来连接两个表达式,并以其右边的表达式的值作为它的结果。逗号的优先级是所有的运算符最低的,所以它两边的表达式会先计算;逗号的组合关系是自左向右,所以左边的表达式会先计算,而右边的表达式的值就留下来作为逗号运算的结果。 逗号运算符一般在for语句中使用。