数据类型详解

10 minBeginner

C 语言的基本类型、派生类型、空类型及其内存布局,包含备考复习要点。

1. 基本数据型 (Basic Types)

1.1 整型 (Integer Types)

C 语言的整型包括以下型:

型 (Type)关键字 (Keyword)典型大小 (Typical Size)格式说明符 (Format Specifier)取值范围 (Range)说明 (Notes)
字符型char1 字节%c / %d-128 到 127 (signed)
0 到 255 (unsigned)
通常用于存储 ASCII 字符。
短整型short2 字节%hd-32768 到 32767用于节省内存。
整型int4 字节%d-2,147,483,648 到 2,147,483,647现代 32/64 位系统中最常用的整型。
长整型long4 或 8 字节%ld取决于系统架构范围大于或等于 int
超长整型long long8 字节%lld-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807C99 引入,保证至少 64 位。

1.2 浮点型 (Floating-Point Types)

型 (Type)关键字 (Keyword)典型大小 (Typical Size)格式说明符 (Format Specifier)精度 (Precision)说明 (Notes)
单精度浮点float4 字节%f6-7 位有效数字精度较低,用于节省内存。
双精度浮点double8 字节%lf15-16 位有效数字默认浮点型,精度较高。
长双精度浮点long double8-16 字节%Lf18-19 位有效数字更高精度,用于科学计算。

1.3 布尔型 (Boolean Type)

  • C99 引入了 _Bool 型,用于表示布尔值(0 或 1)。
  • 通常通过 stdbool.h 头文件使用 bool、“和false 宏:
 #include <stdbool.h>
 int main() {
  bool is_valid = true;
  if (is_valid) {
  printf("Valid\n");
  }
  return 0;
 }

1.4 备考知识点

考点1: 基本数据类型大小

  • 问题: 在32位系统中,int、long、float、double的大小分别是多少?
  • 答案: int: 4字节,long: 4字节,float: 4字节,double: 8字节。 考点2: 格式说明符
  • 问题: 输出long long类型变量应使用什么格式说明符?
  • 答案: %lld

2. 型修饰符 (Type Modifiers)

2.1 符号修饰符

  • signed: 有符号数(默认),支持正负值。
 signed int x = -10; // 可以存储负数
  • unsigned: 无符号数,仅支持 0 和正数,正数范围翻倍。
 unsigned int y = 10; // 只能存储非负数

2.2 存储修饰符

  • const: 声明后不可修改的变量(只读)。
 const int MAX_VALUE = 100; // 常量,不可修改
  • volatile: 告诉编译器不要对该变量进行优化(常见于驱动开发或多线程)。
 volatile int sensor_value; // 防止编译器优化
  • register: 建议编译器将变量存储在寄存器中以提高访问速度(现代编译器通常会自动优化)。
 register int counter; // 建议存储在寄存器中
  • static: 修改变量的存储期和作用域(详见存储)。

2.3 备考知识点

考点1: const修饰符

  • 问题: const修饰符的作用是什么?
  • 答案: 声明变量为只读,不可修改。 考点2: volatile修饰符
  • 问题: volatile修饰符的作用是什么?
  • 答案: 告诉编译器不要对该变量进行优化,适用于多线程或硬件访问场景。

3. 内存大小与 sizeof (Memory & sizeof)

3.1 不同架构下的大小

16位系统32位系统64位系统
char1 字节1 字节1 字节
short2 字节2 字节2 字节
int2 字节4 字节4 字节
long4 字节4 字节8 字节
long long8 字节8 字节8 字节
float4 字节4 字节4 字节
double8 字节8 字节8 字节
void*2 字节4 字节8 字节

3.2 使用 sizeof 运算符

 #include <stdio.h>
 int main() {
  printf("char size: %zu byte\n", sizeof(char));
  printf("short size: %zu bytes\n", sizeof(short));
  printf("int size: %zu bytes\n", sizeof(int));
  printf("long size: %zu bytes\n", sizeof(long));
  printf("long long size: %zu bytes\n", sizeof(long long));
  printf("float size: %zu bytes\n", sizeof(float));
  printf("double size: %zu bytes\n", sizeof(double));
  printf("void* size: %zu bytes\n", sizeof(void*));
  return 0;
 }

3.3 内存对齐

  • 为了提高访问效率,编译器会对变量进行内存对齐。
  • 对齐规则通常是型大小的整数倍。

内存对齐示例

 struct Example {
  char c; // 1字节,但会对齐到4字节
  int i; // 4字节
  double d; // 8字节
 }
 // 在32位系统中,sizeof(struct Example) = 16字节
 // 在64位系统中,sizeof(struct Example) = 24字节

3.4 备考知识点

考点1: sizeof运算符

  • 问题: sizeof运算符的作用是什么?返回什么型?
  • 答案: 计算数据型或变量的字节大小,返回size_t类型。 考点2: 内存对齐
  • 问题: 为什么需要内存对齐?
  • 答案: 提高内存访问效率,因为处理器按字长对齐访问内存。

4. 派生数据型 (Derived Types)

4.1 数组 (Arrays)

  • 相同型数据的有序集合。
  • 声明格式:type array_name[size];
 // 一维数组
 int numbers[5] = {1, 2, 3, 4, 5};
 // 二维数组
 int matrix[3][3] = {
  {1, 2, 3},
  {4, 5, 6},
  {7, 8, 9}
 }
 // 字符数组(字符串)
 char message[] = "Hello, C!";

4.2 指针 (Pointers)

  • 存储内存地址的变量。
  • 声明格式:type *pointer_name;
 int x = 10;
 int *ptr = &x; // ptr 指向 x 的地址
 printf("x 的值: %d\n", x);
 printf("x 的地址: %p\n", &x);
 printf("ptr 存储的地址: %p\n", ptr);
 printf("ptr 指向的值: %d\n", *ptr);
 *
 printf("修改后 x 的值: %d\n", x);

4.3 结构体 (Structures)

  • 不同型数据的组合(用户定义)。
  • 声明格式:
 // 结构体定义
 typedef struct {
  int id;
  char name[50];
  float salary;
 }
 // 结构体使用
 Employee emp1;
 emp1.id = 101;
 strcpy(emp1.name, "John Doe");
 emp1.salary = 5000.0;
 // 结构体初始化
 Employee emp2 = {102, "Jane Smith", 6000.0};

4.4 联合体 (Unions)

  • 共用同一块内存的不同型组合。
  • 所有成员共享同一块内存,修改一个成员会影响其他成员。
 union Data {
  int i;
  float f;
  char str[20];
 }
 data.i = 10;
 printf("data.i: %d\n", data.i);
 data.f = 3.14;
 printf("data.f: %f\n", data.f);
 printf("data.i: %d\n", data.i); // 值已被修改

4.5 枚举 (Enumerations)

  • 为整数常量定义有意义的名称。
  • 默认从 0 开始,也可以显式指定值。
 enum Weekday {
  MONDAY, // 0
  TUESDAY, // 1
  WEDNESDAY, // 2
  THURSDAY, // 3
  FRIDAY, // 4
  SATURDAY, // 5
  SUNDAY // 6
 }
 enum Weekday today = WEDNESDAY;
 printf("Today is day %d\n", today); // 输出 2
 // 显式指定值
 enum Color {
  RED = 1,
  GREEN = 2,
  BLUE = 4
 }

4.6 备考知识点

考点1: 数组与指针

  • 问题: 数组名和指针的关系是什么?
  • 答案: 数组名是指向数组首元素的常量指针考点2: 结构体与联合体的区别
  • 问题: 结构体和联合体的主要区别是什么?
  • 答案: 结构体的每个成员有独立的内存空间,联合体的所有成员共享同一块内存空间。

5. 空型 (Void Type)

5.1 void 型的用途

  • 指定函数的返回类型(无返回值):
 void print_hello() {
 printf("Hello!\n");
 // 无 return 语句
 }
  • 指定函数的参数列表(无参数):
 int main(void) {
 // 代码
 return 0;
 }
  • 声明通用指针 void *(可以指向任何型):
 void *generic_ptr;
 int x = 10;
 generic_ptr = &x;
 char c = 'A';
 generic_ptr = &c;

5.2 备考知识点

考点1: void指针

  • 问题: void指针的特点是什么?
  • 答案: 可以指向任何型的数据,但使用前需要强制型转换。

6. 型转换 (Type Conversion)

6.1 隐式转换 (Implicit Conversion)

  • 编译器自动完成,遵循“从小到大”的原则:
  • charshortintlonglong long
  • floatdoublelong double
  • 整型 → 浮点型
 int x = 10;
 double y = x; // 隐式转换:int → double
 printf("y = %f\n", y); // 输出 10.000000

6.2 显式转换 (Explicit Conversion / Casting)

  • 手动转换,使用圆括号指定目标型:
 double pi = 3.14159;
 int rounded_pi = (int)pi; // 显式转换:double → int
 printf("rounded_pi = %d\n", rounded_pi); // 输出 3
 // 注意:可能会导致数据丢失
 int large_num = 1000000;
 char small_num = (char)large_num; // 可能溢出

6.3 型转换的最佳实践

  • 避免不必要的型转换,保持型一致性。
  • 进行显式转换时,确保转换是安全的,不会导致数据丢失或溢出。
  • 使用括号明确转换的范围,提高代码可读性。

6.4 备考知识点

考点1: 类型转换规则

  • 问题: 隐式型转换的规则是什么?
  • 答案: 从小到大转换,即低精度向高精度转换。 考点2: 强制类型转换
  • 问题: 强制型转换可能带来什么问题?
  • 答案: 可能导致数据丢失、溢出或精度下降。

7. 型定义 (Type Definitions)

7.1 typedef 关键字

  • 为现有型创建别名,提高代码可读性。
 // 为基本类型创建别名
 typedef unsigned int uint;
 typedef long long int64;
 // 为结构体创建别名
 typedef struct {
  int x;
  int y;
 }
 // 使用别名
 uint count = 100;
 int64 large_number = 9999999999;
 Point p = {10, 20};

7.2 标准型定义

  • C 标准库提供了一些标准型定义,如 stdint.h 中的固定宽度整数型:
 #include <stdint.h>
 int8_t s8; // 有符号 8 位整数
 uint8_t u8; // 无符号 8 位整数
 int16_t s16; // 有符号 16 位整数
 uint16_t u16; // 无符号 16 位整数
 int32_t s32; // 有符号 32 位整数
 uint32_t u32; // 无符号 32 位整数
 int64_t s64; // 有符号 64 位整数
 uint64_t u64; // 无符号 64 位整数

7.3 备考知识点

考点1: typedef的作用

  • 问题: typedef关键字的作用是什么?
  • 答案: 为现有型创建别名,提高代码可读性和可维护性。

8. 数据型使用场景

数据适用场景
char存储字符、小整数(-128 到 127)。
short存储较小的整数,节省内存。
int一般整数运算,是最常用的整型。
long存储较大的整数,或需要与平台相关的整数。
long long存储非常大的整数,需要 64 位精度。
float存储浮点数,精度要求不高时使用。
double存储浮点数,精度要求较高时使用(默认)。
long double存储浮点数,需要极高精度时使用。
bool存储布尔值(true/false)。
数组存储相同型的多个元素。
指针存储内存地址,用于动态内存管理、函数参数传递等。
结构体存储不同型的相关数据。
联合体存储不同型的数据,但同一时间只使用一种型。
枚举为整数常量定义有意义的名称,提高代码可读性。

更新日志 (Changelog)

  • 2026-04-05: 深入细化数据型知识。
  • 2026-04-05: 详细扩写内容,增加了布尔型、型修饰符详解、内存对齐、派生型详细示例、型定义和使用场景。