目录
1. 数据类型
(1). 字符型
(2). 整型
(3). 浮点型
(4). 布尔类型
(5). 枚举类型
(6). 不同数据类型的长度
2. signed和unsigned
3. 数据类型的取值范围
(1). 比特(bit/b)
(2). 字节(Byte/B)
(3). 取值范围
4. 变量
(1). 变量的创建
(2). 变量的分类
(3). 变量的存储位置
5. 算数操作符
(1). +和-
(2). *
(3). /
(4). %
6. 赋值操作符
(1). 连续赋值
(2). 复合赋值
7. 单目操作符
(1). ++和--
(2). +和-
8. 强制类型转换
1. 数据类型
(1). 字符型
unsigned char
signed char
char
(2). 整型
//短整型
short [int]
[signed] short [int]
unsigned short [int]
//整型
int
[signed] int
unsigned int
//长整型
long [int]
[signed] long [int]
unsigned long [int]
注意:在C99标准中,加入了更长的整形。
long long [int]
[signed] long long [int]
unsigned long long [int]
用e来表示科学计数法时,规定在e的前面必须有数字,后面如果有数字那就必须为整数。
(3). 浮点型
float
double
long double
(4). 布尔类型
_Bool
C语言中用0表示假,非0值表示真。
后来,在C99 中也引入了布尔类型,是专门表示真假,取值是true或false。
布尔类型的使用得包含头文件<stdbool.h>
(5). 枚举类型
enum
(6). 不同数据类型的长度
sizeof (类型)
sizeof 表达式
sizeof 是一个关键字,也是操作符,专门用来计算sizeof操作符数的类型长度,单位是字节。
sizeof 操作符的操作数可以是类型,也可是变量或者表达式。
sizeof 的操作数如果是表达式,可以省略掉后边的括号。
sizeof 后边的表达式是不参与运算,根据表达式的类型来得出大小。
sizeof 的计算结果是一种size_t类型的无符号整数,在打印时用%zd打印。
注意:
- sizeof中的表达式不计算,其中s是short类型,b+2结果发生截断
- C语言只规定了sizeof(long) ≥ sizeof(int)即可,所以有些系统sizeof(long)=8
2. signed和unsigned
signed,表示一个类型带有正负号,包含负值;
unsigned,表示该类型不带有正负号,只能表示零和正整数。
对于int 类型,默认是带有正负号的,也就是说int 等同于signed int 。这种默认情况关键字signed 一般省略不写,写了也不算错。
int 类型也可以不带正负号,只表示非负整数。这时就必须使用关键字unsigned 声明变量。(unsigned int的int 可以省略)
整数变量声明为unsigned 的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。
比如,16位的signed short int 的取值范围是:-32768~32767,最大是32767;而unsigned short int 的取值范围是:0~65535,最大值增大到了65,535。32位的signed int 的取值范围可以参看limits.h中给出的定义。
字符类型char 也可以设置signed 和unsigned。
注意:C 语言规定char 类型默认是否带有正负号由当前系统决定,可能是signed char ,也有可能是unsigned char 。VS2022中,默认是signed char。
3. 数据类型的取值范围
(1). 比特(bit/b)
CPU能读懂的最小单位,每个比特位只能存放二进制数,即0和1
(2). 字节(Byte/B)
内存机构最小寻址单位,1Byte=8b,1KB=1024Byte,1MB=1024KB,1GB=1024MB
(3). 取值范围
4. 变量
(1). 变量的创建
注意:局部变量不初始化默认是随机值,全局变量不初始化默认为0
(2). 变量的分类
全局变量:在大括号外部定义的变量就是全局变量(全局变量的使用范围更广,整个工程中想使用,都是有办法使用的。)
局部变量:在大括号内部定义的变量就是局部变量(局部变量的使用范围是比较局限,只能在自己所在的局部范围内使用的。)
注意:全局变量与局部变量同名时,局部变量优先。
(3). 变量的存储位置
内存中的三个区域:栈区、堆区、静态区。
局部变量是放在内存的栈区;
全局变量是放在内存的静态区;
堆区是用来动态内存管理的。
5. 算数操作符
(1). +和-
+和-用来完成加法和减法。
+和-都是有2个操作数的,位于操作符两端的就是它们的操作数,这种操作符也叫双目操作符。
(2). *
*用来完成乘法.
(3). /
运算符/用来完成除法。
除号的两端如果是整数,执行的是整数除法,得到的结果也是整数。
上面示例中,尽管变量x 的类型是float(浮点数),但是6 / 4 得到的结果是1.0,而不是1.5。原因就在于C语言里面的整数除法是整除,只会返回整数部分,丢弃小数部分。
如果希望得到浮点数的结果,两个运算数必须至少有一个浮点数,这时 C 语言就会进行浮点数除法。
(4). %
%表示求模运算,即返回两个整数相除的余值。这个运算符只能用于整型,不能用于浮点数。
负数求模的规则:结果的正负号由第一个运算数的正负号决定。
6. 赋值操作符
(1). 连续赋值
赋值操作符可以连续赋值。
C语言虽然支持连续赋值,但是难以理解,建议拆开写,方便观察代码并调试。
(2). 复合赋值
C语言中提供了复合赋值符,方便我们编写代码,这些赋值符有:
7. 单目操作符
C语言中有一些操作符只有一个操作数,即单目操作符。++、--、+(正)、-(负)
(1). ++和--
++是自增操作符,分为前置++和后置++
--是自减操作符,分为前置--和后置--
++在前,先加后用;++在后,先用后加(--同理)
(2). +和-
这里的+是正号,-是负号,都是单目操作符。
运算符+对正负值没有影响,可以省略。
运算符-用来改变值的正负号,负数的前面加上-会得到正数,正数前加-会得到负数。
注意:不可以用--把负值变成正的
8. 强制类型转换
为了消除警告,我们可以使用强制类型转换,把3.14强转为int类型。
9. scanf和printf
(1). printf
printf() 不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换行。为了让光标移到下一行的开头,可以在输出文本的结尾,添加一个换行符\n。
printf() 是在标准库的头文件stdio.h 定义的。使用这个函数之前,必须在源码文件头部引入这个头文件。
(2). 占位符
所谓 “占位符”,就是这个位置可以用其他值代入。
%d 就是占位符,表示这个位置要用其他值来替换。占位符的第一个字符一律为百分号% ,第二个字符表示占位符的类型。
输出文本里面可以使用多个占位符。
printf()参数与占位符是一一对应关系,如果有n个占位符, printf()的参数就应该有n+1个。如果参数个数少于对应的占位符,printf()可能会输出任意值。
• %a :十六进制浮点数,字母输出为小写。
• %A :十六进制浮点数,字母输出为大写。
• %c :字符。
• %d :十进制整数。
• %e :使用科学计数法的浮点数,指数部分的e为小写。
• %E :使用科学计数法的浮点数,指数部分的E为大写。
• %i :整数,基本等同于%d 。
• %f :小数(包含float 类型和double 类型)。
• %g :6个有效数字的浮点数。整数部分一旦超过6位,就会自动转为科学计数法,指数部分的e为小写。
• %G :等同于%g ,区别是指数部分的E 为大写。
• %hd :十进制 short int 类型。
• %ho :八进制 short int 类型。
• %hx :十六进制 short int 类型。
• %hu :unsigned short int 类型。
• %ld :十进制 long int 类型。
• %lo :八进制 long int 类型。
• %lx :十六进制 long int 类型。
• %lu :unsigned long int 类型。
• %lld :十进制 long long int 类型。
• %llo :八进制 long long int 类型。
• %llx :十六进制 long long int 类型。
• %llu :unsigned long long int 类型。
• %Le :科学计数法表示的 long double 类型浮点数。
• %Lf :long double 类型浮点数。
• %n :已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中。
• %o :八进制整数。
• %p :指针。
• %s :字符串。
• %u :无符号整数(unsigned int)。
• %x :十六进制整数。
• %zd : size_t类型。
• %% :输出一个百分号。
printf()允许限定占位符的最小宽度。
%5d 表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。输出的值默认是右对齐,即输出内容前面会有空格;如果希望改成左对齐(在输出内容后面添加空格),可以在占位符的%的后面插入一个-号。
注意:如果打印的数超过这个占位符的宽度,就会原样打印这个数。
对于小数,这个限定符会限制所有数字的最小显示宽度。
%12f表示输出的浮点数最少要占据12位。由于小数的默认显示精度是小数点后6位,所以123.45 输出结果的头部会添加2个空格(小数点也占据1位)。
输出小数时,可以限定小数点后面的位数。
对于小数的两种写法可以组合使用。
注意:打印printf("%8f\n", 123.45),输出的是123.450000,因为小数点后面必须要满6位,没有就补0
最小宽度和小数位数这两个限定值,都可以用 * 代替,通过printf()的参数传入。
默认情况下, printf()只对负数显示-号。如果想正数和负数都显示正负号,可以在%后面加一个+。
%s 占位符用来输出字符串,默认是全部输出。如果只想输出开头的部分,可以用%.[m]s 指定输出的长度,其中[m] 代表一个数字,表示所要输出的长度。
(3). scanf
注意:scanf在vs2022中直接使用会报错,会让你改成scanf_s。但是scanf_s是vs2022提供的,不是c语言里的,代码就失去了可移植性。因此应该在文件的开头加上
scanf() 的语法跟printf() 类似。
上面示例中, scanf( ) 的第一个参数%d ,表示用户输入的应该是一个整数。%d 就是一个占位符, % 是占位符的标志, d 表示整数。&i表示,将用户从键盘输入的整数存入变量i 。
注意:变量前面必须加上&(指针变量除外),因为scanf( )传递的是地址,即将i的地址指向用户输入的值。如果这里的变量是指针变量(比如字符串变量),那就不用加&运算符。
scanf() 处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。所以,用户输入的数据之间,有一个或多个空格不影响scanf() 解读数据。另外,用户使用回车键,将输入分成几行,也不影响解读。
scanf() 处理用户输入的原理是,用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。
解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。
上面示例中,%d忽略起首的空格,因为小数点不属于整数的有效字符。所以%d 只读到-13 。
第二次调用scanf() 时,就会从上一次停止的地方,继续往下读取。这一次读取的首字符是小数点,由于对应的占位符是%f,会读取到.45e12 ,这是采用科学计数法的浮点数格式。后面的#不属于浮点数的有效字符,所以会在#停止。
scanf( )的返回值是一个整数,表示成功读取的变量个数。
如果没有读取任何项,或者匹配失败,则返回0 。如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF。
注意:一个数字都不输入时,scanf的返回值不是0,而是-1
scanf() 常用的占位符如下,与printf() 的占位符基本一致。
• %c :字符。
• %d :整数。
• %f : float 类型浮点数。
• %lf : double 类型浮点数。
• %Lf : long double 类型浮点数。
• %s :字符串。
• %[ ] :在方括号中指定一组匹配的字符(比如%[0-9]),遇到不在集合之中的字符,匹配将会停止。
注意:
- 除了%c ,scanf都会自动忽略起首的空白字符。%c 不忽略空白字符,无论该字符是否为空格,总是返回当前第一个字符。如果要强制跳过字符前的空白字符,可以写成scanf(" %c", &ch) ,即%c 前加上一个空格,表示跳过零个或多个空白字符。
- %s不能简单地等同于字符串。它的规则是,从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)停止读取。因为%s不会包含空白字符,所以无法用来读取多个单词,除非多个%s 一起使用。这也意味着,scanf( )不适合读取可能包含空格的字符串。
- scanf() 遇到%s占位符,会在字符串变量末尾存储一个空字符\0 。scanf( )将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串时,很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,使用 %s 占位符时,应该指定读入字符串的最长长度,即写成%[m]s ,其中的[m] 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃。
上面示例中,如果用户输入 2020-01-01 ,就会正确解读出年、月、日。问题是用户可能输入其他格式,比如2020/01/01 ,这种情况下, scanf() 解析数据就会失败。
为了避免这种情况, scanf() 提供了一个赋值忽略符*。只要把*加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃。
上面示例中, %*c就是在占位符的百分号后面,加入了赋值忽略符* ,表示这个占位符没有对应的变量,解读后不必返回。