目录
- 1. 变量和常量数据
- 2. 数据:数据类型关键字
- 3. 基本数据类型
- 4. 使用数据类型
1. 变量和常量数据
-
常量(constant):在程序使用前已经设定好,在整个程序的运行过程中不会发生变化
-
变量(variable):在程序运行期间可能会改变或被赋值
#include <stdio.h>
int main() {
int i = 1;
// i: 变量
// 1: 常量
}
2. 数据:数据类型关键字
初始关键字 | C90添加关键字 | C99添加关键字 |
---|---|---|
int | signed | _Bool |
long | void | _Complex |
short | _Imaginary | |
unsigned | ||
char | ||
float | ||
double |
- 位、字节和字
- 位:bit,用于存储0和1
- 字节:byte
- 1byte = 8bits
- 字:word
- 根据操作系统的位数决定,位数即为字长
- 8位系统:1word = 8bits
- 16位系统:1word = 16bits
- 32位系统:1word = 32bits
- 64位系统:1word = 64bits
- 根据操作系统的位数决定,位数即为字长
2.1 整数
正确 | 错误 |
---|---|
2、-23、2456 | 3.14、0.22、2.000 |
0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 字长8位 | |
---|---|---|---|---|---|---|---|---|---|
2^2 | 2^1 | 2^0 | |||||||
4 | + 2 | + 1 | = 7 | 整数7 |
2.2 浮点数
正确 | 错误 |
---|---|
2.75、3.16E7、7.00、2e-8 | 7 |
- E/e 记数法:3.16E7 = 3.16 * 10 ^ 7
+ | 0.316 | 8 | |
---|---|---|---|
符号 | 小数 | 指数 | |
+ | 0.316 | * 10 ^ 8 | = 3.16 * 10 ^ 7 |
2.3 区别
整数 | 浮点数 |
---|---|
没有小数部分 | 有小数部分 |
表示范围较小 | 表示范围较大 |
对于一些算数计算(两个大数相减)精度损失较小 | 精度损失较大 |
实际值 | 实际值的近似值 |
运算较快 | 运算较慢(通过CPU上的浮点处理器弥补) |
3. 基本数据类型
3.1 int类型
- 有符号整型
- 16位
- 取值范围:- 2 ^ 31 ~ 2 ^ 31 - 1
3.1.1 获取值的途径
-
赋值
int i; // 创建内存空间 i = 1;
-
通过函数获取
int i; scanf("%d", &i);
-
初始化变量
int i = 1; // 创建内存空间,并为其赋值
3.1.2 打印
#include <stdio.h>
int main() {
int i = 1;
int j = 2;
printf("i = %d, j = %d\n", i, j);
// i = 1, j = 2
printf("i = %d, j = %d\n", i);
// i = 1, j = 11604003
// j为脏数据
}
3.1.3 八进制和十六进制
- 八进制:以 0 开头
- 十六进制:以 0x 或 0X 开头
3.1.4 显示八进制和十六进制
符号 | 含义 |
---|---|
%d | 以十进制显示数字 |
%o | 以八进制显示数字 |
%x 或 %X | 以十六进制显示数字 |
%#o | 以八进制显示数字,并附带前缀 |
%#x 或 %#X | 以十六进制显示数字,并附带前缀 |
3.2 其他整数类型
符号 | 含义 |
---|---|
short (int) | 占用空间比 int 少,有符号整型,16位 |
long (int) | 占用空间比 int 多,有符号整型,32位 |
long long (int) | 占用空间比 long 多,有符号整型,64位 |
unsigned (int) | 无符号整型,0 ~ 2^16 - 1 |
- C90添加 unsigned long 和 unsigned short
- C99添加 unsigned long long
- 在任何有符号类型前加关键字 signed ,可强调使用有符号类型的意图
3.2.1 long 常量和 long long 常量
-
使用 l 或 L 后缀表示 long 类型
int i1 = 1; // 16位存储 int i2 = 1l; // singned long // 32位存储 int j = 2uL; // unsigned long
-
使用 ll 或 LL 后缀表示 long long 类型
int i = 1ll; // singned long long int j = 2uLL; // unsigned long long
3.2.2 整数溢出
#include <stdio.h>
int main() {
int i = 2147483647;
int j = 4294967295u;
printf("%d, %d, %d\n", i, i+1, i+2);
// 2147483647, -2147483648, -2147483647
printf("%u, %u, %u\n", j, j+1, j+2);
// 4294967295, 0, 1
}
3.2.3 打印
符号 | 含义 |
---|---|
%ld | 以十进制打印 long |
%lx | 以十六进制打印 long |
%lo | 以八进制打印 long |
%hd | 以十进制打印 short |
%hl | 以十六进制打印 short |
%ho | 以八进制打印 short |
%u | 打印 unsigned int |
%lu | 打印 unsigned long |
%lld | 以十进制打印 long long |
%llu | 打印 unsigned long long |
3.3 使用字符:char类型
- 存储字符(字母或标点符号)
- char 实际上存储的是整数而不是字符
- 计算机用数字编码处理字符
- 一定为1个字节,即8位
3.3.1 声明
char a;
char b, c;
3.3.2 字符常量和初始化
char a = 'A';
// 初始化
// a: 变量
// 'A': 常量
char a = 65;
// 将 ASCII码 65 对应的字符赋值给 a
语句 | T / F |
---|---|
a = ‘A’; | T |
a = A; | F,此时 A 为变量 |
a = “A”; | F,此时 “A” 为字符串 |
难点(坑)(P45)
- C语言将字符常量视为 int 类型而非 char 类型
- int:32 位、char:8位
- 原本字符常量对应的ASCII码存储在32位的存储单元中,现在可以存储在8位的存储单元中
#include <stdio.h>
int main() {
char a = 'ABCD';
// 把4个独立的8位ASCII码存储在一个32位存储单元中
char b = a;
// 只有最后8位有效
printf("%c\n", b);
// D
}
3.3.3 非打印字符
转义字符 | 含义 | 应用 |
---|---|---|
\a | 警报(ANSI C) | 发出一声蜂鸣,但不移动光标 |
\b | 退格 | |
\f | 换页 | 将活跃位置移至下一页开始处(可能显示成奇怪的符号) |
\n | 换行 | 将活跃位置移至下一行开始处 |
\r | 回车 | 将活跃位置移至当前行开始处 |
\t | 水平制表符 | 将活跃位置移至下一个水平制表点 |
\v | 垂直制表符 | 将活跃位置移至下一个垂直制表点(可能显示成奇怪的符号) |
\ | 反斜杠(\) | |
\’ | 单引号 | |
\" | 双引号 | |
\? | 问号 | |
\0oo | 八进制(oo为有效的八进制数) | 使用该八进制数的ASCII码对应的字符 |
\xhhh | 十六进制(hhh为有效的十六进制数) | 使用该十六进制数的ASCII码对应的字符 |
3.3.4 打印
#include <stdio.h>
int main() {
char c = ' ';
scanf("%c", &c);
// a
printf("%c = %d\n", c, c);
// a = 97
}
3.3.5 是否有符号(坑)
- 不同的编译器对于char的符号类型定义不同
- 有的编译器把char实现为有符号类型,char可表示范围为 -2^7 ~ 2^7 - 1
- 有的编译器把char实现为无符号类型,char可表示范围为 0 ~ 2^8 - 1
- C90标准下,C语言允许在关键字 char 前使用 signed 和 unsigned
3.4 _Bool类型
- C99标准添加了_Bool 类型,用于表示布尔值,即逻辑 true 和 false
- C语言使用 1 表示 true,0 表示 false
- _Bool类型实际上也为一种整数类型,仅占用1位存储空间
3.5 可移植类型:stdint.h 和 inttypes.h
-
C99新增
-
某些类型名在不同系统中的功能不同,因而引入 stdint.h 和 inttypes.h,以确保C语言的类型在各系统中的功能相同
-
stdint.h:现有类型名的别名
-
精准宽度整数类型(exact-width integer type):
-
C99提供
-
int32_t:宽度正好是32位的整数类型
-
计算机的底层系统可能无法支持
-
-
最小宽度类型(minimum width type):
-
C99 和 C11 提供
-
int_least8_t:可容纳8位有符号整数值的类型中宽度最小的类型
-
-
最快最小宽度类型(fastest minimum width type):
- C99 和 C11 提供
- int_fast8_t:系统中对8位有符号值而言运算最快的整数类型
-
最大整数类型
- C99提供
- intmax_t:最大的有符号整数类型
- uintmax_t:最大的无符号整数类型
-
-
inttypes.h:字符串宏以用来显示可移植类型
- PRId32:打印32位有符号值得合适转换说明(d / l)
3.6 float、double 和 long double
- 浮点数的表示类似于科学记数法,即用小数乘以10的幂来表示数字
例子 | 科学记数法 | 指数记数法 |
---|---|---|
1000000000 | 1.0 * 10 ^ 9 | 1.0e9 |
123000 | 1.23 * 10 ^ 5 | 1.23e5 |
322.56 | 3.2256 * 10 ^ 2 | 3.2256e2 |
0.000056 | 5.6 * 10 ^ -5 | 5.6e-5 |
- float:单精度
- 至少能表示6位有效数字,且取值范围至少为10 ^ -37 ~ 10 ^ 37
- 通常,系统存储一个 float 要占用32位
- 8位用于表示指数的值和符号
- 24位用于表示非指数部分及其符号
- double:双精度
- 至少能表示10位有效数字,且取值范围至少为10 ^ -37 ~ 10 ^ 37
- 通常,系统存储一个 double 要占用64位
- 有的系统将多出的32位全部用来表示非指数部分,增加有效数字的位数(提高精度),减少舍入误差
- 有的系统将多出的32位中的一些位表示指数部分,增加可表示数的范围
- long double:比 double 精度更高
- C只保证 long double 类型至少与 double 类型的精度相同
3.6.1 声明
float f;
double d;
long double ld;
3.6.2 浮点型常量
- 编译器假定浮点型常量是 double 类型的精度,计算精度更高,但是减慢程序的运行速度
float f;
f = 1.1;
// 1.1: 常量
// double
f = 1.1f;
// float
f = 1.1L;
// long double
- C99 添加用十六进制表示浮点型常量
- 在十六进制前加前缀 0x 或 0X
- 用 p 或 P 分别代替 e 和 E,用 2 的幂代替 10 的幂
0x | a | .1f | p10 | |
---|---|---|---|---|
十六进制 | (10 | + 1/16 + 15/256) | * 2^ 10 | = 10364.0 |
3.6.3 打印
- 编译器会把 float 类型自动转换成 double 类型
符号 | 含义 |
---|---|
%f | 以十进制记数法打印 float 和 double |
%e | 以指数记数法打印 float 和 double |
%a | 以十六进制记数法打印 float 和 double |
%lf | 以十进制记数法打印 long float 和 long double |
#include <stdio.h>
int main() {
float f = 1.0;
double d = 2.0;
long double ld = 3.0;
printf("%f = %e = %a\n", f, f, f);
// 1.000000 = 1.000000e+00 = 0x1.0000000000000p+0
printf("%f = %e\n", d, d);
// 2.000000 = 2.000000e+00
printf("%lf = %le\n", ld, ld);
// 3.000000 = 3.000000e+00
}
3.6.4 浮点值的上溢和下溢
- 上溢(overflow):
- 计算导致数字过大,超过当前类型能表达的范围
- 发生此情况时,C语言会给变量赋一个很大的值,并显示该值为 inf 或 infinity(无穷)
float f = 3.4e38 * 100.0f;
printf("%e\n", f);
// inf
- 下溢(underflow):
- 低于正常的(subnormal)浮点值:计算导致数字过小,损失原末尾有效位上的数字
#include <stdio.h>
int main() {
float f = 0.1234e-2;
printf("%f / 10 = %f\n", f, f / 10);
// 0.001234 / 10 = 0.000123
}
- 特殊的浮点数值:NaN,计算的行为未被定义
3.7 复数和虚数类型
- C99提供
- 复数:
- float_Complex:
- 包含两个 float 类型的值,分别表示实部和虚部
- double_Complex
- long double_Complex
- float_Complex:
- 虚数:
- float_Imaginary
- double_Imaginary
- long double_Imaginary
- 如果包含 complex.h 头文件,可以用 complex 替换 _Complex,imaginary 替换 _Imaginary
3.8 其他类型
- 数组
- 指针
- 结构
- 联合
3.9 类型大小
- sizeof():以字节为单位输出指定类型的大小
- C99 和 C11 提供 %zd 匹配 sizeof() 的返回值类型
- 不支持 C99 和 C11 的编译器可以使用 %u 和 %lu 代替 %zd
#include <stdio.h>
int main() {
printf("int : %zd\n", sizeof(int));
// int : 4
printf("char : %zd\n", sizeof(char));
// char : 1
printf("long : %zd\n", sizeof(long));
// long : 4
printf("long long : %zd\n", sizeof(long long));
// long long : 8
printf("double : %zd\n", sizeof(double));
// double : 8
printf("long double : %zd\n", sizeof(long double));
// long double : 8
}
4. 使用数据类型
- 初始化变量应使用与变量类型匹配的常数类型
示例 | T / F |
---|---|
int i = 1; | T |
int i = 1.0; | F,可以赋值,不推荐 |
int i = 1.5; | F,可以赋值,只会保留整数位 |
float f = 3.1415926536; | F,可能会警告,只会保留6位有效数字 |