计算机的存储
计算机中最小的存储单元是位(bit),可以存储0或1,常用的存储单位是字节(byte),1字节均为8位,而字(word)是设计计算机时给定的自然存储单位。
数据类型
① signed和unsigned
C语言使用 signed 和 unsigned 关键字修饰字符型和整型类型的。
signed 关键字,表示一个类型带有正负号,包含负值;
unsigned 关键字,表示该类型不带有正负号,只能表示零和正整数。
② 整数类型
整数类型 | 字节 | 最小值 | 最大值 |
short | 2 | -32768 | 32767 |
unsigned short | 2 | 0 | 65535 |
int | 4 | -2147483648 | 2147483647 |
unsigned int | 4 | 0 | 4294967295 |
long | 4 | -2147483648 | 2147483647 |
unsigned long | 4 | 0 | 4294967295 |
long long | 8 | -9223372036854775808 | 9223372036854775808 |
unsigned long long | 8 | 0 | 18446744073709551615 |
八进制和十六进制
一个以0开始的数字字面量是八进制
一个以0x开始的数字字面量是十六进制
整数溢出
当超过最大值时,unsigned int 类型的变量j从0开始,而int类型的变量 i 从 -2147483648 开始。
③ 浮点型
flaot 是单精度浮点型(使用4字节来存储),精度为小数点后6位;double 是双精度浮点型(使用8字节来存储),精度为小数点后15位。
在浮点数后面加上f或F后缀可覆盖默认设置,编译器会将浮点类型常量看作 float 类型,如1.6f 和 20.23113F。使用l或L后缀使得数字成为 long double 类型(建议使用L,l和数字1容易混淆)。没有后缀的浮点型常量是 double 类型。
浮点型 | 字节 | 最小值 | 最大值 |
float | 4 | 1.17549e-38 | 3.40282e+38 |
double | 8 | 2.22507e-308 | 1.79769e+308 |
long double | 8 | 2.22507e-308 | 1.79769e+308 |
浮点值上溢
当计算导致数字过大,超出当前类型能表达的范围时,C语言规定在这种情况下会给 max 赋一个无穷大的值。(inf 或 infinity 具有无穷大含义)
④ 字符型
在C语言中,用单引号括起来的单个字符被称为字符常量。编译器一发现 'A',就会将其转换成相应的代码值(ASCII码)。单引号必不可少。
char name; //声明一个char类型的变量
name = 'B'; //此时'B'是一个字符
name = B; //此时B是变量
name = "B"; //此时"B"是一个字符串
char name = 66; //对于ASCII,这样做没问题,但在不同环境中,name的值可能不是B
字符型 | 字节 | 最小值 | 最大值 |
char | 1 | -128 | 127 |
unsigned char | 1 | 0 | 255 |
字符串
使用双引号括起来的一串字符就被称为字符串,用双引号括起来的单个字符也被称为字符串。
因为在C语言中没有专门用于存储字符串的变量类型,字符串都被存储在char类型的数组中。数组由连续的存储单元组成,每个单元存储一个字符。例如:"my name is cc!"
m | y | n | a | m | e | i | s | c | c | ! | \0 | ||||
每 | 个 | 存 | 储 | 单 | 元 | 1 | 字 | 节 | 空字符 |
数组末尾位置的字符\0,是空字符(ASCII码值是0),C语言用它标记字符串的结束。C语言中的字符串一定以空字符结束,这意味着数组的容量必须至少比待存储字符串中的字符数多1。
什么是数组?可以把数组看作是一行连续的多个存储单元,严格来说数组是同类型数据元素的有序序列。例如:char name[5],name 后面的方括号表明这是一个数组,方括号中的5表明该数组中的元素数量。
ASCII码值
字符A~Z的ASCII码值从65~90,字符a~z的ASCII码值从97~122。(对应的大小写字符 a和A的 ASCII码值的差值是32)
数字字符0~9的ASCII码值从48~57
在这些字符中ASCII码值从0~31 这32个字符是不可打印字符,无法打印在屏幕上观察
非打印字符
转义序列 | 含义 |
\a | 警报 |
\b | 退格 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\\ | 反斜杠 |
\' | 单引号 |
\'' | 双引号 |
\? | 问号 |
\0oo | 八进制值(每个o可表示0~7中的一个数) |
\xhh | 十六进制值(每个o可表示0~f中的一个数) |
⑤ 布尔类型
—Bool 类型用于表示布尔值,即逻辑值 true 和 faluse。因为C语言中用值1表示 true,值0表示false,所以 —Bool 类型实际上也是一种整数类型。它仅占用1位存储空间。
sizeof 和strlen
sizeof
①sizeof 是C语言的内置运算符,也是一个关键字,以字节为单位给出指定类型的大小。
②sizeof 操作符的操作数可以是类型,也可是变量或者表达式。
#include <stdio.h>
int main()
{
int cc = 10;
printf("%zd\n", sizeof(int));
printf("%zd\n", sizeof(cc));
printf("%zd\n", sizeof(10 + 3.0));
return 0;
}
③sizeof 的操作数如果不是类型,是表达式的时候,可以省略掉后边的括号的。(个人建议还是所有情况下都使用圆括号)
#include <stdio.h>
int main()
{
int cc = 10;
printf("%zd\n", sizeof(cc));
printf("%zd\n", sizeof cc); //cc是变量的名字,可以省略掉sizeof后边的()
printf("%zd\n", sizeof(13));
printf("%zd\n", sizeof 13); //13是一个特定量,可以省略掉sizeof后边的()
return 0;
}
④sizeof 后边的表达式是不真实参与运算的,根据表达式的类型来得出大小
⑤sizeof 的计算结果是 size_t 类型的。
sizeof 运算符的返回值,C语言只规定是无符号整数,并没有规定具体类型,而是留给系统自己去决定,sizeof 到底返回什么类型。对此C语言提供了一个解决方法,创造了一个类型别名size_t,用来统一表示 sizeof 的返回值类型。
strlen
strlen()函数给出字符串中的字符长度。与sizeof 不同的是strlen函数知道在何处停止。让我们看个例子:
从图我们可以看到 sizeof 运算符报告,name 数组有20个存储单元。但是,只有前4个单元用来存储 tian,所以 strlen()得出的结果是4。name 数组的第5个单元存储空字符,strlen()并未将其计入。
可能会有人问为什么只存储了4个字符?那是因为在 scanf 终端输入字符串时,如果在终端输入空格,系统就会默认是 '\0' 结束符号,无论后边有多少个字符或空格都不会被获取长度。
让我们再看一个例子:strlen()和 sizeof 的区别
对于 age ,用 strlen()得出的也是字符串中的字符数(包括空格和标点符号)。然而,sizeof 运算符给出的数更大,因为它把字符串末尾不可见的空字符也计算在内。
可能又有人会问为什么这次把空格也读取了?那是因为 char 数组存储字符串时,系统把空格当作 ' ' ,是一个字符,而不是 '\0' ,并且系统会在字符串的末尾自动添加一个 '\0' 结束符号。
算数操作符
① + 和 - 和 *
进行 + 、- 和 * 运算的前提条件是需要有两个数(操作数),所以 + 、 - 和 * 是双目操作符。
② / 和 %
/ 是双目操作符,可用于整数和浮点数。
为什么a的值是6.000000,而不是6.500000?那是因为在 C 语言里面的整数除法是整除,只会返回整数部分,丢弃小数部分。那就是说尽管 a 是浮点数,但13 / 2的计算结果是6.0,而不是6.5。
如果希望得到浮点数的结果,两个运算数必须至少有⼀个浮点数,这时 C 语言就会进行浮点数除法。让我们再看一下下面这个例子:
% 是双目操作符, 运算符 % 表示求模(余)运算,即返回两个整数相除的余值, 但只能用于整数。
③ = 和 +=
赋值和连续赋值
复合赋值
④ + 和 - 、++ 和 --
++ 和 --
可能有人会问 a++ 和 ++a 有什么区别?让我们看下面这个例子:
在这里我先简单介绍一下 if 语句,if 语句的(),括号里面是一个条件,当这个条件为真时,才会执行中括号里面的语句。而在 if 语句中如果条件的值为一个非0常数,则这个条件为真,将执行中括号里面的语句;如果条件的值为0,则这个条件为假,不会执行中括号里面的语句。
在这个例子中,为什么 a 和 b 的数值一样,但只输出 haha,而没有输出 hehe? 那是因为 a++ 这个条件为假,++b 为真。所以我们就可以理解,a++ 是先使用 a 的值进行判定,再进行 a = a + 1,而 ++b 是先进行 b = b + 1,再使用 b 的值进行判定,这就解释了为什么只打印haha,而不打印 hehe。
总结:前置++,先+1再使用。后置++,先使用再加1。前置--,先减1再使用。后置--,先使用再减1。(a++ 称为后置++,++a 称为前置++)
+ 和 -
强制类型转换
在下面这个代码中 a 是 int 类型,而1.13是 float 类型,这句代码的意思是将1.13强行类型转换为 int 类型,并且这种强制类型转换只取整数部分。(只能说最好不这样用)
本文内容结束啦,希望各位大佬多多指教!
感谢大家三连支持!
敬请期待下篇文章!