type简介
在C语言中,typedef
是用于为现有的数据类型定义一个新的类型名称的关键字。它的作用是为类型取一个别名,使代码更简洁、更易于理解。
基本语法
typedef 原始类型 新类型名;
示例
-
为
int
类型定义一个别名:typedef int INTEGER; INTEGER a = 10; // 这里的 a 实际上是 int 类型的变量
-
为结构体定义别名:
struct Point { int x; int y; }; typedef struct Point POINT; POINT p1; // 现在可以直接用 POINT 来声明结构体变量
typedef
的用途
- 简化复杂类型定义:当类型非常复杂时,可以用
typedef
提供简洁的别名。 - 提高代码可读性:通过为数据类型起一个具备语义的名字,代码可读性更高。
- 便于移植:通过使用
typedef
,可以在需要修改类型时只修改一处代码。
总结来说,typedef
提供了一种方法来使代码更加清晰、简洁,同时也方便类型的管理和修改。
在linux内核中的应用
在 Linux 内核中,typedef
被广泛用于简化复杂类型的定义,并提升代码的可读性。内核代码中使用了许多通过 typedef
定义的常见数据类型,以下是一些常用的 typedef
定义的数据类型:
1. 基本整数类型
Linux 内核中定义了一些固定大小的整数类型,确保在不同的硬件平台上能够保持一致性。
-
u8
,u16
,u32
,u64
: 无符号整数,分别为 8、16、32 和 64 位。typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64;
-
s8
,s16
,s32
,s64
: 有符号整数,分别为 8、16、32 和 64 位。typedef signed char s8; typedef signed short s16; typedef signed int s32; typedef signed long long s64;
2. 布尔类型
内核中没有 C 标准库的 bool
类型,因此定义了自己的布尔类型。
-
bool
: 定义布尔类型,用于表示true
或false
。typedef _Bool bool;
-
true
和false
: 用于表示布尔值。#define true 1 #define false 0
3. 大小和指针相关的类型
-
size_t
: 表示对象大小的类型,通常用于内存分配函数中(如malloc
或kmalloc
)。typedef unsigned long size_t;
-
ssize_t
: 与size_t
类似,但它是有符号的,用于表示函数返回值,如读写函数的返回值。typedef long ssize_t;
-
ptrdiff_t
: 用于存储两个指针之间的差值。typedef long ptrdiff_t;
4. 内核特定类型
-
pid_t
: 用于表示进程 ID。typedef int pid_t;
-
gid_t
,uid_t
: 分别用于表示组 ID 和用户 ID。typedef unsigned int gid_t; typedef unsigned int uid_t;
5. 内存管理相关类型
gfp_t
: 用于表示内存分配标志,在内存分配函数中用来指定如何分配内存。typedef unsigned int gfp_t;
6. 时间相关类型
-
time_t
: 用于表示时间值,通常是自 Unix 纪元以来的秒数。typedef long time_t;
-
clock_t
: 用于表示时钟周期数。typedef long clock_t;
-
ktime_t
: 表示内核时间的一种类型,用于高精度时间操作。typedef s64 ktime_t;
7. 页帧和物理地址相关类型
-
pfn_t
: 表示页面帧编号(Page Frame Number),与物理内存地址相关。typedef unsigned long pfn_t;
-
phys_addr_t
: 表示物理内存地址。typedef unsigned long phys_addr_t;
8. 位操作相关类型
u64
和atomic_t
: 用于位操作和原子操作。u64
是 64 位无符号整数,atomic_t
是内核定义的原子类型,用于保证多核环境下的原子操作。typedef struct { int counter; } atomic_t;
这些 typedef
定义不仅让代码更简洁,还增强了可移植性和可维护性,使内核代码在不同架构上运行时具有一致的行为。
其他类型
在 Linux 内核中,为了处理不同硬件平台可能采用的不同字节序(大端或小端),定义了许多与字节序相关的类型。字节序决定了多字节数据在内存中的存储顺序。以下是通过 typedef
定义的用于小端序(Little Endian)处理的常用类型:
1. 小端序的整数类型
这些类型专门用于表示小端序的固定大小整数,确保在不同平台上能够正确处理内存中的数据字节顺序。
-
__le16
: 16 位无符号小端整数typedef __u16 __le16;
-
__le32
: 32 位无符号小端整数typedef __u32 __le32;
-
__le64
: 64 位无符号小端整数typedef __u64 __le64;
2. 与大小端无关的基础类型
在内核中,还定义了一些无关大小端的基础类型,方便在大小端环境中进行跨平台处理。
-
__u8
: 8 位无符号整数,字节序不相关,因为 8 位不需要考虑字节序。typedef unsigned char __u8;
-
__u16
: 16 位无符号整数typedef unsigned short __u16;
-
__u32
: 32 位无符号整数typedef unsigned int __u32;
-
__u64
: 64 位无符号整数typedef unsigned long long __u64;
3. 大端序的整数类型
虽然你问的是小端序,但为了完整性,这里也列出常用于大端序处理的类型。
-
__be16
: 16 位无符号大端整数typedef __u16 __be16;
-
__be32
: 32 位无符号大端整数typedef __u32 __be32;
-
__be64
: 64 位无符号大端整数typedef __u64 __be64;
4. 类型转换辅助函数
为了确保在不同平台上处理数据时能够正确转换字节序,Linux 内核中还提供了很多字节序转换的辅助函数:
-
小端转 CPU 本地字节序:
le16_to_cpu()
:将小端 16 位数据转换为 CPU 本地字节序。le32_to_cpu()
:将小端 32 位数据转换为 CPU 本地字节序。le64_to_cpu()
:将小端 64 位数据转换为 CPU 本地字节序。
-
CPU 本地字节序转小端:
cpu_to_le16()
:将 CPU 本地 16 位数据转换为小端序。cpu_to_le32()
:将 CPU 本地 32 位数据转换为小端序。cpu_to_le64()
:将 CPU 本地 64 位数据转换为小端序。
这些 typedef
和字节序转换函数有助于处理网络协议、文件格式以及跨平台开发中的数据传输问题,确保数据能够正确地在不同字节序的系统中存储和读取。