目录
c语言数据类型
C 中的类型可分为以下几种:
序号 | 类型与描述 |
1 | 基本数据类型 |
2 | 枚举类型: |
3 | void 类型: |
4 | 派生类型: |
基本数据类型:整型(int)、字符型(char)、浮点型(float)和双精度浮点型(double)
signed ---有符号,unsiged---无符号
signed char 就是char ,signed 可以省略,同理,
signed int 就是 int ,
signed short 就是short等等
一、整数类型
整数类型简称整型,就是用于存放整数值的,比如:12,30,3456等。
整型注意事项
- 各类型存储大小受到操作系统、编译器、硬件平台的影响。
- 整型分为有符号signed和无符号unsigned两种,默认是signed。
- 开发中使用整型一般用int型,如果不足以表示大数,可以使用long long。
字面量后缀
字面量是源代码中一个固定值的表示法,用于直接表示数据,如图所示:
- 一个整数字面量默认是int类型。
- 如果需要表示 long 类型字面量,需要添加后缀 l 或 L。
- 如果需要表示 long long 类型字面量,需要添加后缀 ll 或 LL。
- 如果需要表示无符号整数字面量,需要添加后缀 u 或 U, 注意, u 和 l 可以结合使用,不分先后,如 ul(无符号long类型)、ULL(无符号 long long类型),lu(无符号 long 类型) 等。
格式占位符
- %d 对应 int 类型,%u 对应 unsigned int 类型。
- %lld 对应 long long 类型,%llu 对应 unsigned long long 类型。
- %ld 对应 long 类型,%lu 对应 unsigned long 类型。
- %hd 对应 short 类型,%hu 对应 unsigned short 类型。
代码演示:
#include <stdio.h>
int main()
{
// 声明short类型的变量,并赋值
short s1 = 10;
signed short s2 = -10; // 相当于 short s1 = -10;
unsigned short s3 = 20;
// 输出有符号和无符号的s1,s2,s3变量的值
printf("有符号的short变量s1 = %hd, s2 = %hd, 无符号的short变量s3 = %hu \n", s1, s2, s3);
// short变量也都可以使用%d占位符
printf("有符号的short变量s1 = %d, s2 = %hd, 无符号的short变量s3 = %d \n", s1, s2, s3);
printf("============\n");
// 声明int类型的变量,并赋值
int i1 = 10;
signed int i2 = -10;
unsigned int i3 = 20u; // 等同于 unsigned i4 = 20u;
// 输出有符号和无符号的i1,i2,i3变量的值
printf("有符号的int变量i1 = %d, i2 = %d, 无符号int变量i3 = %d \n", i1, i2, i3);
printf("============\n");
// 声明long类型的变量,并赋值
long l1 = 100l;
signed long l2 = -100l; // 相当于 long l2 = -100l
unsigned long l3 = 1000LU;
// 输出有符号和无符号的l1,l2,l3变量的值
printf("有符号的long变量l1 = %ld, l2 =%ld, 无符号的long变量l3 = %lu \n", l1, l2, l3);
// 声明long long 类型的变量,并赋值
long long ll1 = 1000l;
signed long long ll2 = -1000ll;
unsigned long long ll3 = 1000LLU;
// 输出有符号和无符号的ll1,ll2,ll3变量的值
printf("有符号的long long变量ll1 = %lld ,ll2 = %lld, 无符号的long long变量ll3 = %llu \n", ll1, ll2, ll3);
return 0;
}
输出结果:
有符号的short变量s1 = 10, s2 = -10, 无符号的short变量s3 = 20
有符号的short变量s1 = 10, s2 = -10, 无符号的short变量s3 = 20
============
有符号的int变量i1 = 10, i2 = -10, 无符号int变量i3 = 20
============
有符号的long变量l1 = 100, l2 =-100, 无符号的long变量l3 = 1000
有符号的long long变量ll1 = 1000 ,ll2 = -1000, 无符号的long long变量ll3 = 1000
精确宽度类型
C 语言的整数类型(short、int、long)在不同计算机上,占用的字节宽度可能是不一样的。程序员有时需要精准的字节宽度,以提高代码的可移植性,尤其是嵌入式开发中,使用精确宽度类型可以确保代码在各种平台上的一致性。
标准库的头文件 <stdint.h> 中定义了一些新的类型别名,如下:
类型名称 | 含义 |
int8_t | 8 位有符号整数 |
int16_t | 16 位有符号整数 |
int32_t | 32 位有符号整数 |
int64_t | 64 位有符号整数 |
uint8_t | 8 位无符号整数 |
uint16_t | 16 位无符号整数 |
uint32_t | 32 位无符号整数 |
uint64_t | 64 位无符号整数 |
上面这些都是类型别名,编译器会指定它们指向的底层类型。比如,某个系统中,如果 int 类型为32位, int32_t 就会指向 int ;如果 long 类型为32位, int32_t 则会指向 long 。
二、浮点类型
浮点类型可以表示一个小数,比如:123.4,7.8,0.12等。
类型 | 存储大小 | 值范围 | 精度 |
float 单精度 | 4 字节 | 1.2E-38 到 3.4E+38 | 6~ 9位有效位 |
double双精度 | 8 字节 | 2.3E-308 到 1.7E+308 | 15~ 18 位有效位 |
long double 长双精度 | 32位:10字节 64位:16字节 | 32位:与double相同或更大 64位:3.4E-4932 到 1.1E+4932 | 18/19或更多 |
浮点型注意事项
- 各类型的存储大小和精度受到操作系统、编译器、硬件平台的影响。
- 浮点型数据有两种表示形式。十进制数形式:如:5.12、512.0f、.512(0.512 可以省略 0)科学计数法形式:如:5.12e2、5.12E-2
- 开发中用到浮点型数字,建议使用double型,如精度要求更高可以使用long double 型。
字面量后缀
- 浮点数字面量默认是double型,
- 如果需要表示long double类型字面量,需加后缀 l 或 L。
- 如果需要表示float类型字面量,须加后缀 f 或 F。
格式占位符
在C语言中,占位符是一种用于格式化输出的特殊字符,通常用于 printf() 等输出函数中,用于指定输出的格式和内容。
- %f 是浮点类型的格式占位符,在printf中对应double类型(float类型会转换成double来处理);默认会保留6位小数,可以指定小数位数,如:%.2f 表示保留2位小数。
- %lf在printf中和 %f意思相同(C99标准加入),也对应double类型,默认保留6位小数,可以指定小数位数,如:%.2lf 表示保留2位小数。但需要注意的是,在scanf中 %lf和 %f含义不同:输入一个float类型数据时使用 %f;而输入double类型时必须使用 %lf。
- %Lf 对应的是long double 类型,默认保留6位小数,可以指定小数位数,如: %.2Lf 表示保留2位小数。需要注意的是,输入输出 long double 类型都必须使用 %Lf 占位符。
- %e 对应科学计数法表示的浮点数,可以指定尾数部分所保留的小数位数,如 %.2e 表示尾数部分保留两位小数。
代码演示:
#include <stdio.h>
int main()
{
// 声明float类型的变量
float f1 = 0.12345f;
float f2 = 3.11592f;
float f3 = -2e12f;
float f4 = 1.9823e2f;
// 输出单精度浮点型的变量数据,%f表示浮点类型的格式占位符,%e表示科学计数法的格式占位符
printf("f1 = %f,f2 = %f, f3 = %.2f, f4 = %f \n", f1, f2, f3, f4);
printf("f1 = %e, f2 = %.2e, f3 = %e, f4 = %e \n", f1, f2, f3, f4);
double d1 = 3.1415926;
double d2 = 0.123456;
double d3 = -2e12f;
double d4 = 1.9823e2;
printf("d1 =%lf, d2 =%.2lf, d3 =%lf, d4 =%lf \n", d1, d2, d3, d4);
printf("d1 = %e, d2 = %.2e, d3 =%e, d4 = %e \n", d1, d2, d3, d4);
return 0;
}
输出结果:
f1 = 0.123450,f2 = 3.115920, f3 = -1999999991808.00, f4 = 198.229996
f1 = 1.234500e-01, f2 = 3.12e+00,f3= -2.000000e+12,f4 = 1.982300e+02
d1 = 3.141593, d2 = 0.12,d3 = -1999999991808.000000, d4 = 198.230000
d1 = 3.141593e+00, d2 = 1.23e-01,d3 =-2.000000e+12,d4 = 1.982300e+02
三、字符类型
字符类型 char 可以表示单个字符,如一个数字、一个字母、一个符号。
注意事项
- char类型的字面量是用单引号括起来的单个字符。
- 多个字符称为字符串,在C语言中使用char数组表示,数组不是基本数据类型,而是构造类型。
格式占位符
使用%c表示char类型。
字符类型本质
- C语言中,char类型本质是一个整数,是ASCII码中对应的数字,存储长度是 1 个字节,char类型也可以进行数学运算。
- 字符型同样分为signed char(无符号)和unsigned char(有符号),其中signed char取值范围-128 ~ 127,unsigned char取值范围0 ~ 255。默认是否带符号取决于当前运行环境。
代码演示:
#include <stdio.h>
int main()
{
// 声明char类型的变量并赋值,字面量数据需要单引号进行包裹
char c1 = 'A';
char c2 = '9';
char c3 = '\t';
printf("c1 = %c, c2 = %c, c3 = %c \n", c1, c2, c3);
// char 类型本质上是整数类型,其范围是0~255之间,是ASCII码的扩展
char c4 = 'A';
char c5 = 97;
printf("c4 = %c, c4 = %d \n", c4, c4);
printf("c5 = %c, c5 = %d \n", c5, c5);
printf("c4+c5= %d \n", c4 + c5);
// char类型的取值范围
signed char c6 = 200; // 有符号的char 取值范围是-128~127之间
unsigned char c7 = 200; // 无符号的char 取值范围是0-255之间,超出范围
char c8 = 200; // 当前系统默认是有符号的char
printf("c6 = %d, c7 = %d, c8 = %d", c6, c7, c8);
return 0;
}
输出结果:
c1 = A, c2 = 9, c3 =
c4 = A, c4 = 65
c5 = a, c5 = 97
c4+c5= 162
c6 = -56, c7 = 200, c8 = -56
200的二进制数是1100 1000
char类型,假如没有unsigned修饰的话,范围是-128~127
+56是0011 1000,反码1100 0111,
-56是+56的补码1100 1000
200超出范围了char数值表达的最大范围。
所以1100 1000的第一个1是它的符号位,为负。表示的数值就是-56
四、布尔类型
布尔值用于表示真、假两种状态,通常用于逻辑运算和条件判断。
C99标准还提供了一个头文件 <stdbool.h> 定义了bool代表_Bool,true代表1,false代表0。
#include <stdio.h>
#include <stdbool.h>
int main()
{
bool b1 = false;
bool b2 = true;
printf("b1 = %d, b2 = %d \n", b1, b2);
if (b1)
{
printf("b1 is true");
}
if (b2)
{
printf("b2 is true");
}
return 0;
}
输出结果:
b1 = 0, b2 = 1, b3 = 1
b2 is true
五、获取数据的存储大小
使用sizeof
可以获取数据类型或变量、字面量的存储大小,单位是字节。sizeof返回一个size_t类型的无符号整数值,格式占位符是 %zu。size_t
通常是 unsigned int
或 unsigned long
的别名,具体是哪个类型的别名,由系统和编译器决定。
代码演示:
#include <stdio.h>
/***********************************************
* sizeof的基本使用,返回值类型是size_t,占位符是:%zu
************************************************/
int main()
{
// 计算数据类型的字节大小,必须使用小括号将数据类型关键字包裹起来
printf("char占字节大小为:%zu \n", sizeof(char)); // 1
printf("short占字节大小为:%zu \n", sizeof(short)); // 2
printf("int占字节大小为:%zu \n", sizeof(int)); // 4
printf("long占字节大小为:%zu \n", sizeof(long)); // 4
printf("long long占字节大小为:%zu \n", sizeof(long long)); // 8
printf("float占字节大小为:%zu \n", sizeof(float)); // 4
printf("double占字节大小为:%zu \n", sizeof(double)); // 8
printf("long double占字节大小为:%zu \n", sizeof(long double)); // 16
printf("====================\n");
// 计算字面量数据的字节大小,可以省略括号
printf("字符a的字节大小:%zu \n", sizeof 'a'); // 4
printf("整数100的字节大小:%zu \n", sizeof 100); // 4
printf("浮点数3.14的字节大小:%zu \n", sizeof 3.14f); // 4
printf("====================\n");
// 计算变量数据的字节大小,可以省略括号
char a = 'a';
int b = 10;
long long c = 100;
double d = 100.345;
printf("变量a的字节大小为:%zu \n", sizeof a); // 1
printf("变量b的字节大小为:%zu \n", sizeof b); // 4
printf("变量c的字节大小为:%zu \n", sizeof c); // 8
printf("变量d的字节大小为:%zu \n", sizeof d); // 8
return 0;
}
输出结果:
char占字节大小为:1
short占字节大小为:2
int占字节大小为:4
long占字节大小为:4
long long占字节大小为:8
float占字节大小为:4
double占字节大小为:8
long double占字节大小为:16
====================
字符a的字节大小:4
整数100的字节大小:4
浮点数3.14的字节大小:4
====================
变量a的字节大小为:1
变量b的字节大小为:4
变量c的字节大小为:8
变量d的字节大小为:8
字符型常量,不属浮点数常量,而归属于 int 型。所以,字符型 char 常量占四个字节。
六、数据类型转换
c语言中不同类型的数据在运算和赋值的时候会进行类型转换,分为:隐式转换(自动类型转换)和显示转换(强制类型转换)。
1.自动类型转换(隐式转换)
转换规则
- 不同类型整数进行运算,窄类型整数自动转换为宽类型整数。
- 整数与浮点数进行运算,整数自动转换为浮点数。
- 不同类型浮点数进行运算,精度小的类型自动转换为精度大的类型。
转换方向
代码演示:
#include <stdio.h>
int main()
{
// 不同类型的数据进行运算,小转大(窄类型转宽类型)
short s1 = 10;
int i1 = 20;
// 运算过程中short类型的s1会自动的转换成int类型
printf("s1+i1=%d \n", s1 + i1); // 30
printf("================\n");
// 有符号的整数会转成无符号的整数
signed int a = -10;
unsigned int b = 5;
// 负数转为无符号整数,两者绝对值的和是无符号整数的最大值再加 1
// -10+ 2^32+5
// -10+4294967296=4294967286+5=4294967291
printf("a+b=%u \n", a + b);
printf("================\n");
// 不同浮点数运算,精度低的会转成精度高的
float f1 = 35.45f;
double d1 = 50.123;
printf("f1+d1=%.10f \n", f1 + d1);
printf("================\n");
// 整型和浮点型进行运算,会转成浮点型
int i2 = 100;
double d2 = 10.12345;
printf("i1+d2=%.2f \n", i2 + d2);
printf("================\n");
return 0;
}
输出结果:
s1+i1=30
================
a+b=4294967291
================
f1+d1=85.5730007629
================
i1+d2=110.12
2.强制类型转换(显式转换)
隐式类型转换中的宽类型赋值给窄类型,编译器是会产生警告的,提示程序存在潜在的隐患,如果非常明确地希望转换数据类型,就需要用到强制(或显式)类型转换。
转换格式
(类型名)变量、常量或表达式
代码演示:
#include <stdio.h>
int main()
{
double d1 = 3.987;
double d2 = 4.235;
int sum1 = d1 + d2; // 先相加,后传int
int sum2 = (int)d1 + (int)d2; // d1转int为3,d2转int为4 结果为:7
int sum3 = (int)(d1 + d2); // 先相加,后传int
int sum4 = (int)(2.5 * 10 + 2 * 1.5);
printf("sum1 = %d \n", sum1);
printf("sum2 = %d \n", sum2);
printf("sum3 = %d \n", sum3);
printf("sum4 = %d \n", sum4);
return 0;
}
输出结果:
sum1 = 8
sum2 = 7
sum3 = 8
sum4 = 28