C 语言的数据类型有很多,可以分为 4 大类型:
void 类型 基本类型 字符类型 有符号整数类型 无符号整数类型 浮点类型 枚举类型 派生类型 数组类型 结构体类型 联合体类型(也叫共同体类型) 函数类型 指针类型
一、基本类型
有符号整数类型
char
(等价类型:signed char
)short
(等价类型:signed short
、short int
、signed short int
)int
(等价类型:signed int
、signed
)long
(等价类型:signed long
、long int
、signed long int
)(C99 起)long long
(等价类型:signed long long
、long long int
、signed long long in
t`)(C99 起)无符号整数类型
unsigned char unsigned short(等价类型: unsigned short int
)unsigned int(等价类型: unsigned
)unsigned long(等价类型: unsigned long int
)(C99 起)unsigned long long(等价类型: unsigned long long int
)(C99 起)字符类型
char
浮点类型
float
double
long double
1.1. 整数类型
1.1.1. 整数类型大小
C 标准规定
1 == sizeof(char)
<= sizeof(short)
<= sizeof(int)
<= sizeof(long)
<= sizeof(long long)复制
1.1.2. 数据模型
关于基本类型大小的是实现方案,统称为:数据模型。有 4 种常见的数据模型
32bit 系统(指针为 32 位)
Win32 API Unix、类 Unix 系统(Linux、Mac OS X) Win16 API LP32 ILP32 64bit 系统(指针为 64 位)
Unix、类 Unix 系统(Linux、Mac OS X) Win64 API LLP64 LP64 比较少见的数据模型
仅出现在早期 64 位 Unix 系统(例如 Unicos on Cray) ILP64:int、long、指针均为 64 位

1.1.3. 有符号整数类型和无符号整数类型区别
整数类型可分为:有符号整数类型、无符号整数类型。
1.1.4. 有符号整数 char、无符号整数 unsigned char
// 0xBD <=> 0b10111101
char c1 = 0xBD;
unsigned char c2 = 0xBD;
printf("%d %d", c1, c2); // 输出:-67 189复制

// 0x43 <=> 0b01000011
char c1 = 0x43;
unsigned char c2 = 0x43;
printf("%d %d", c1, c2); // 输出:67 67复制

c1、c2 变量在内存中存放的二进制数据是完全一样的; 对于同一份二进制数据,分别以有符号数形式、无符号数形式解读出来的含义可能是不一样的。
1.1.5. 整数的取值范围
char
、unsigned char
都只占用一个字节,能够存放的二进制数据范围都是[0b0000 0000, 0b1111 1111]
。
char
的取值范围:unsigned char
的取值范围:有 n 个二进制位的有符号数的取值范围 有 n 个二进制位的无符号数的取值范围
位数 | 符号 | 最小值 | 最大值 |
---|---|---|---|
8 | 有符号 | ||
8 | 无符号 | 0 | |
16 | 有符号 | ||
16 | 无符号 | 0 | |
32 | 有符号 | ||
32 | 无符号 | 0 | |
64 | 有符号 | ||
64 | 无符号 | 0 |
1.1.6. 溢出(Overflow)
溢出指的是内容超过了已知容器的容量。
例:short s;
short
类型的变量 s 有 2 个字节的内存空间如果要将超过 2 个字节(比如 4 个字节)的数据存储到变量 s 中去,就会产生内存溢出
案例一:
int i = 16909292;
short s = 16909292;
char c = i;
printf("%d\n", i); // 输出:16909292
printf("%d\n", s); // 输出:1004
printf("%d\n", c); // 输出:-20复制

当出现溢出时,会优先保留低字节的数据,舍弃高字节的数据; 所以在给取值范围小的变量赋值时要注意防止数据溢出,否则结果可能会跟预期不符合。
思考:那是不是以后都统一使用取值范围比较大的变量就好了?应该根据已知的数据范围选择合适大小的变量,不然会造成内存空间的浪费
案例二:
int i = 16909292;
char c = i;
i = c;
printf("%d\n", i); // 输出:-20
printf("%d\n", c); // 输出:-20复制

案例三:
unsigned char c1 = 255;
char c2 = -1;复制

c1 = c1 + 1;
c2 = c2 + 1;
printf("c1=%d, c2=%d", c1, c2); // 输出:c1=0, c2=0复制

案例四:
unsigned char c1 = 0;
char c2 = 0;复制

c1 = c1 - 1;
c2 = c2 - 1;
printf("c1=%d, c2=%d", c1, c2); // 输出:c1=255, c2=-1复制

案例五:
unsigned char c1 = 127;
char c2 = 127;复制

c1 = c1 + 1;
c2 = c2 + 1;
printf("c1=%d, c2=%d", c1, c2); // 输出:c1=128, c2=-128复制

案例六:
unsigned char c1 = 128;
char c2 = -128;复制

c1 = c1 - 1;
c2 = c2 - 1;
printf("c1=%d, c2=%d", c1, c2); // 输出:c1=127, c2=127复制

案例七:
unsigned char c1 = 255;
char c2 = -1;复制

c1 = c1 + 1;
c2 = c2 + 1;
printf("c1=%d, c2=%d", c1, c2); // 输出:c1=0, c2=0复制

案例八:
unsigned char c1 = 0;
char c2 = 0;复制

c1 = c1 - 1;
c2 = c2 - 1;
printf("c1=%d, c2=%d", c1, c2); // 输出:c1=255, c2=-1复制

1.1.7. unsigned char、char 的取值范围

1.2. 浮点类型
浮点类型可以用来表示小数(比如 3.14),包括float
,double
,long double
类型
最常用的浮点类型是float
和double
,一般在数值后面加上 f 或者 F 表示十 float 类型的数值
float f = 3.14F;
double d = 10.24;
printf("%f %f", f, d); // 输出:3.140000 10.240000复制
float
:单精度(Single)浮点类型,占用 32bit,可以保证精确到小数点后 6 位最小值: 最大值: double
:双精度(Double)浮点类型,占用 64bit,可以保证精确到小数点后 15 位最小值: 最大值:
1.2.1. 浮点类型的存储细节
思考:为什么 32bit 的
unsigned int
最大值是 2^32-1,而 32bit 的float
最大值是 3.4 * 10^38?因为他们的存储方式不一样,浮点数在计算机中是按照 IEEE 754 标准存储的。
1.3. 整数、浮点数字面量
char c = 10;
unsigned char uc = 10;
short s = 10;
unsigned short us = 10;
int i = 10;
unsigned int ui1 = 10u;
unsigned int ui2 = 10U;
long l1 = 10l;
long l2 = 10L;
unsigned long ul1 = 10ul;
unsigned long ul2 = 10UL;
// 不能是lL或Ll
long long ll1 = 10ll;
long long ll2 = 10ll;
float f1 = 10.24F;
double d1 = 10.24;
// 小数部分可选:1.0
float f2 = 1.F;
double d2 = 1.;
// 整数部分可选:0.1
float f3 = .1F;
double d3 = .1;
// 十进制小数 1.2 * 10^3 = 1200.0
float f4 = 1.2e3F; // 1.2E3F
double d4 = 1.2e3; // 1.2E3
// 十六进制小数 1.125 * 2^10 = 1152.0
float f5 = 0x1.2p10F; // 0x1.2P10F
double d5 = 0x1.2p10; // 0x1.2P10
// 十进制 1.875 * 2^3 = 15.0
printf("%f", 0x1.ep+3); // 可写:0x1.EP+3 输出:15.000000
// 十进制 1.875 * 2^(-2) = 0.46875
printf("%f", 0x1.ep-2); // 可写:0x1.EP-2 输出:0.468750
int v 0xE+2; // 错误
int x = 0xe+2; // 错误
int y = 0xA+2; // OK
int z = 0xE +2; // OK
int q = (0xE)+2 // OK复制
1.4. printf 中的转换格式指定符

1.4.1. 案例一
printf("%zd\n", sizeof(int)); // 输出:4
long long age = 10LL;
printf("%lld\n", age); // 输出:10
unsigned long no = 8UL;
printf("%lu\n", no); // 输出:8
char *name = "idbeny";
char *place = "1024星球";
printf("我是%s,欢迎来到%s\n", name, place); // 输出:我是idbeny,欢迎来到1024星球复制
1.4.2. 案例二
// 用%%来显示一个%
printf("%d%%%d\n", 10, 20); // 输出:10%20
int i1 = 10;
// %6d表示占用6个字符位置,默认靠右对齐(左边空白)
printf("welcome%6d24星球\n", i1); // 输出:welcome 1024星球
// %-6d表示占用6个字符位置,靠左对齐(右边空白)
printf("welcome%-6d24星球\n", i1); // 输出:welcome10 24星球
int i2 = -6;
// %+6d:加号(+)表示显示正负号
printf("%+6d和%+-6d\n", i1, i2); // 输出: +10和-6
double d = 3.1415926;
// 四舍五入保留2位小数
printf("%.2f\n", d); // 输出:3.14
/*
* 占用10个字符位置
* 四舍五入保留4位小数
* 显示正负号
* 靠左对齐
*/
printf("1%+-10.4f2\n", d); // 输出:1+3.1416 2复制
1.5. scanf 中的转换格式指定符
// 用%%来匹配一个%
int age = 10;
scanf("%%%d", &age); // 输入:%30
printf("age is %d\n", age); // 输出:age is 30
/*
输入:30
输出:age is 10
输入:%30
输出:age is 30
*/
// 在scanf中,float类型用%f
float f;
scanf("%f", &f);
// 在scanf中,double类型用%lf
double d;
scanf("%lf", &d);
// 在printf中,float、double都可以用%f、%lf
printf("%f %lf %f %lf", f, f, d, d);
/*
输入:10(回车)20
输出:10.000000 10.000000 20.000000 20.000000
*/
int i1 = 1;
int i2 = 2;
// %*3d是跳过长度为3的整数
scanf("%2d%*3d%4d", &i1, &i2);
printf("i1=%d,i2=%d", i1, i2);
/*
输入:10 20 40
输出:i1=10,i2=40
输入:10111140
输出:i1=10,i2=140
*/复制
1.6. 类型转换
格式:
类型1 v1 = xx;
类型2 v2 = (类型1)v1;复制
案例:
char c = 'A';
int i = (int)c;
printf("%d\n", i); // 输出:65
int i2 = 200;
short s = (short)i2;
printf("%d\n", s); // 输出:200
// 会丢失精度
double d = 3.14;
int i3 = (int)d;
printf("%d\n", i3); // 输出:3
int i4 = 333;
double d2 = (double)i4;
printf("%f\n", d2); // 输出:333.000000复制
其实在很多时候,编译器都会进行隐式类型转换:
char c = 'A';
int i = c;
printf("%d\n", i); // 输出:65
int i2 = 200L;
short s = i2;
printf("%d\n", s); // 输出:200
double d = 3.14;
int i3 = d;
printf("%d\n", i3); // 输出:3
int i4 = 333;
double d2 = i4;
printf("%f\n", d2); // 输出:333.000000复制
大类型转小类型的时候,可能会丢失精度:
double d = 3.14;
printf("%f\n", d); // 输出:3.140000
int i = d;
printf("%d\n", i); // 输出:3
double d2 = 1.1234567890123456789123;
printf("%.20f\n", d2); // 输出:1.12345678901234569125
float f = d2;
printf("%.20f\n", f); // 输出:1.12345683574676513672复制
文章转载自1024星球,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
2025年4月中国数据库流行度排行榜:OB高分复登顶,崖山稳驭撼十强
墨天轮编辑部
1864次阅读
2025-04-09 15:33:27
2025年3月国产数据库大事记
墨天轮编辑部
866次阅读
2025-04-03 15:21:16
2025年3月国产数据库中标情况一览:TDSQL大单622万、GaussDB大单581万……
通讯员
602次阅读
2025-04-10 15:35:48
征文大赛 |「码」上数据库—— KWDB 2025 创作者计划启动
KaiwuDB
495次阅读
2025-04-01 20:42:12
数据库,没有关税却有壁垒
多明戈教你玩狼人杀
485次阅读
2025-04-11 09:38:42
国产数据库需要扩大场景覆盖面才能在竞争中更有优势
白鳝的洞穴
463次阅读
2025-04-14 09:40:20
最近我为什么不写评论国产数据库的文章了
白鳝的洞穴
403次阅读
2025-04-07 09:44:54
天津市政府数据库框采结果公布!
通讯员
359次阅读
2025-04-10 12:32:35
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
353次阅读
2025-04-17 17:02:24
优炫数据库成功入围新疆维吾尔自治区行政事业单位数据库2025年框架协议采购!
优炫软件
336次阅读
2025-04-18 10:01:22