大家好,欢迎来到IT知识分享网。
C 语言数据类型概览
数据类型,是编程语言的基石。其最初的目的就是为了让程序(开发者)更加充分的利用稀缺的内存资源。随着技术的发展,数据类型也被赋予了更深厚的含义:
- 用于确定数据对象占用的内存空间大小。
- 用于确定数据对象的数值范围。
- 用于规定数据对象所能进行的操作(行为)。
例如:基本整型数据对象占用 4B 的内存空间,数值范围是 [0x0, 0xFFFF FFFF],可以进行算术运算。

四大数据类型
- 「基本数据类型」:是 C 语言中最基本的数据类型,它们用于存储基本的数据值,包括:整型、浮点型、字符型和布尔型。
- 「构造数据类型」:由多个基本数据类型组成,它们用于表示更复杂的数据结构,包括:数组、结构体、联合体和枚举类型。
- 「指针类型」:用于存储变量或数据的内存地址。
- 「空类型(void)」:是一种特殊的数据类型,它表示没有值。空类型通常用于表示函数没有返回值,或者指针没有指向任何数据。
- 「衍生数据类型」:是通过对其他类型进行修改而得到的新类型。C 语言中常见的衍生数据类型包括:常量类型、限定符类型和自定义类型。
基本数据类型取值范围概览

数值类型
整型
整型又可以细分为 int、long、long long 这 3 类。
对于整型数据而言,我们首先需要关心的是整型的进制表示方式,这涉及到数值前缀。
- 「10 进制(默认)」
- 「2 进制(以 0b 开头)」:0b
- 「8 进制(以 0 开头)」:045,021
- 「16 进制(以 0x 开头)」:0x21458adf
而后,因为整型数据有 signed 和 unsigned 之分,以及 int 和 long 之分,这涉及到数值后缀。
- 「u 表示 unsigned」
- 「l 表示 long」
85 /* 十进制 */ 0213 /* 八进制 */ 0x4b /* 十六进制 */ 30 /* 整数 */ 30u /* 无符号整数 */ 30l /* 长整数 */ 30ul /* 无符号长整数 */
浮点型

在这里插入图片描述
浮点型可细分为 float(单精度)和 double(双精度)这 2 类,代码写法有所不同:
- 「double(默认)」:2.3
- 「float」:2.3f
- 「long double」:2.3lf
另外,浮点数有 2 种表达方式:
- 「小数形式」。
- 「指数形式(科学计数法)」:由数符尾数(整数或小数)、阶码标志(E 或 e)、阶符、整数阶码组成的常数。例如:2.e+001。
3.14159 /* 合法的 */ E-5L /* 合法的 */ 510E /* 非法的:不完整的指数 */ 210f /* 非法的:没有小数或指数 */ .e55 /* 非法的:缺少整数或分数 */
示例:
#include <stdio.h> #include <float.h> // 定义了浮点型相关的宏,e.g. FLT_MIN、FLT_MAX 等。 int main(){ printf("float byte: %lu \n", sizeof(float)); printf("float MIN: %E \n", FLT_MIN); // 以指数形式输出单、双精度实数。 printf("float MAX: %E \n", FLT_MAX); printf("float DIG: %d \n", FLT_DIG); return 0; }
运行:
$ ./main float byte: 4 float MIN: 1.E-38 float MAX: 3.E+38 float DIG: 6
字符类型
字符型
字符型(Char)数据需要使用单引号 ‘c’ 括起来,占用 1B 内存空间,范围是 [-128, 127] 与 ASCII 码的编号对应。另外,字符型数据本质是一个 “数字“,所以可以和整型数据相互转换。

字符型数据具有 2 种类型:
- 「一般字符数据」:一个用单引号 ‘ ‘ 括起来的字符。
- 「转义字符数据」:一个用单引号 ‘ ‘ 括起的,并以反斜杠 ” 开头的字符,用于表示具有特殊功能的字符。
下表列出了转义序列表:

无符号和有符号的区别
只有整型和字符型数据具有无符号和有符号的特性。
对于同一种数据类型而言,有符号的区别就在于具有 “符号位”,所以,虽然两者都占用相同的内存空间,但拥有的数值范围却不同。
例如:若 unsigned char 和 signed char 都占用 1B 的内存空间。那么,signed char 的数值范围为 [-128, 127],而 unsigned char 的数据范围为 [0, 255]。这是因为有符号类型数据的最高位被用作为符号位。

CPU 平台适配
值得注意的是,C 语言基本数据类型的实际大小还与 CPU 的字长(32bit 还是 64bit)有关。为了让程序对不同的 CPU 具有更好兼容性,C 提供了 sizeof 关键字和 size_t 数据类型。
sizeof 关键字
sizeof 关键字用于获得某个数据类型在当前 CPU 平台上的准确大小(字节数)。
int main() { char stringA[] = "Hello World!\r\n"; printf(" sizeif( char ) = %d\r\n", sizeof(char)); printf(" sizeif( int ) = %d\r\n", sizeof(int)); printf(" sizeif( long int ) = %d\r\n", sizeof(long int)); printf(" sizeif( float ) = %d\r\n", sizeof(float)); printf(" sizeif( double ) = %d\r\n", sizeof(double)); // 注意 stringA 的末尾还存放着 '\0' printf(" sizeif( stringA ) = %d\r\n", sizeof(stringA)/sizeof(char)); return 0; }
size_t 自定义数据类型
在 C 程序中使用 size_t(size_type)可以有效提高代码的跨平台可移植性和可读性。C 语言原生数据类型并不包含 size_t,而是 C 标准委员会为了解决程序可移植性问题才引入的。sizeof() 函数返回值就是 size_t 类型。
_t 后缀的含义是 type,表明这是 POSIX 或 GNU 保留的一种数据类型,防止命名空间污染(Namespace Pollution)。POSIX 规定 C 语言自身扩展的类型都有 _t 后缀,这样就不会与用户自定义的类型的命名冲突了。
size_t 的定义在 stddef.h、stdio.h、stdlib.h、string.h、time.h 和 wchar.h 这些标准 C 的头文件中,include l了以上任一头文件,则表明 size_t 将作为一个全局关键字。
- 在 32bit CPU 平台中的定义:
typedef unsigned int size_t;
- 在 64bit CPU 平台中的定义:
typedef unsigned long size_t;
可见,size_t 是一种无符号的整型(unsigned int、unsigned long、unsigned long long),取值范围是目标 CPU 平台中最大的可能范围。
#include <stdio.h> int main() { printf("Int size: %d", sizeof(int)); } // Int size: 4
为什么需要额外引入一个 size_t 自定义数据类型呢?本质上是为了弥补整型数据类型在 CPU 地址线宽度不匹配的缺陷。
在 C 语言种,整型数据类型的大小通常会小于等于 CPU 数据线的宽度,例如:int 对应的数据线宽度普遍是 32bit,而地址线的宽度普遍是 64bit。所以引入了 size_t 类型,它通常会大于等于 CPU 地址线宽度,以此来表示 CPU 平台中最大的可能范围。
size_t 数据类型的另一个好处是见名知义,通常只用于表示 “字节大小” 或 “数量”,而不是一个普通的算术值,适当地使用 size_t 会使你的代码变得更加可读。
C 的标准函数中大量使用到了 size_t 类型来表示取值的字节数:
void *malloc(size_t size); void *memcpy(void *s1, void const *s2, size_t size); size_t strlen(char const *s);
uintX_t 类型
在 C99 标准的 stdint.h 头文件中通过 typedef 定义了 uint8_t、uint_16_t、uint32_t、uint64_t 等数据类型,同样是为了优化跨 64bit 或 32bit CPU 平台的可移植性。
格式化输出符为:
- uint16_t:%hu
- uint32_t:%u
- uint64_t:%llu
- uint8_t:本质是一个 char 类型,所以在输出 uint8_t 类型的变量时,实际上输出了其对应的字符,而不是数值。
#ifndef __int8_t_defined # define __int8_t_defined typedef signed char int8_t; typedef short int int16_t; typedef int int32_t; # if __WORDSIZE == 64 typedef long int int64_t; # else __extension__ typedef long long int int64_t; # endif #endif typedef unsigned char uint8_t; typedef unsigned short int uint16_t; #ifndef __uint32_t_defined typedef unsigned int uint32_t; # define __uint32_t_defined #endif #if __WORDSIZE == 64 typedef unsigned long int uint64_t; #else __extension__ typedef unsigned long long int uint64_t; #endif
– END –
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/179017.html