typedef定义时,类型别名与原类型有何区别?

99ANYc3cd6
预计阅读时长 18 分钟
位置: 首页 C语言 正文

typedef 是 C 语言中的一个关键字,它的作用是为已有的数据类型创建一个新的名称(别名),它本身并不创建新的数据类型,而是为现有的类型定义了一个更容易理解、更简洁或更具描述性的别名。

c语言 typedef定义
(图片来源网络,侵删)

可以把 typedef 理解为“类型定义器”或“类型重命名器”。


typedef 的基本语法

typedef 的语法结构非常清晰:

typedef existing_type new_type_name;
  • existing_type:已经存在的数据类型(可以是基本类型、指针、数组、结构体、联合体等)。
  • new_type_name:你为这个类型定义的新名字。

一个简单的例子:

假设我们经常需要使用一个 unsigned long long 类型来表示内存地址或大数值,每次都写 unsigned long long 会很繁琐。

c语言 typedef定义
(图片来源网络,侵删)
#include <stdio.h>
// 使用 typedef 为 unsigned long long 创建一个别名
typedef unsigned long long ull;
int main() {
    // 我们可以直接使用 ull 来定义变量
    ull a = 18446744073709551615ULL; // 比 unsigned long long 简洁多了
    ull b = 0xFFFFFFFFFFFFFFFF;
    printf("a = %llu\n", a);
    printf("b = %llu\n", b);
    return 0;
}

在这个例子中,ull unsigned long long 的别名,在编译时,编译器会把所有出现的 ull 都替换成 unsigned long long


typedef 的主要用途和优点

使用 typedef 主要有以下好处:

  1. 提高代码可读性:为复杂的类型起一个有意义的名字,使代码意图更明确。
  2. 简化代码:用简短的别名代替冗长的类型声明。
  3. 提高代码可移植性:当需要修改数据类型时,只需修改 typedef 定义,而不需要在整个代码库中替换所有该类型的使用。
  4. 增强代码的自文档性:好的类型名本身就是一种文档。

typedef 的常见用法详解

typedef 的强大之处在于它可以和各种数据类型结合使用。

为基本数据类型定义别名

这是最简单的用法,通常用于增加可读性。

c语言 typedef定义
(图片来源网络,侵删)
typedef unsigned int uint;      // 无符号整型
typedef unsigned char uchar;    // 无字符型
typedef float real;             // 实数
typedef long distance;          // 距离

为数组类型定义别名

这非常实用,特别是对于多维数组和函数指针数组。

// 定义一个包含 10 个 int 元素的数组类型
typedef int INT_ARRAY_10[10];
int main() {
    INT_ARRAY_10 arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    INT_ARRAY_10 arr2;
    // arr1 和 arr2 都是包含 10 个 int 的数组
    for (int i = 0; i < 10; i++) {
        printf("%d ", arr1[i]);
    }
    printf("\n");
    return 0;
}

为指针类型定义别名

这是 typedef 最常见的用途之一,可以极大地简化指针的声明。

a) 指向基本数据类型的指针

typedef int* IntPtr; // IntPtr 是一个指向 int 的指针类型
int main() {
    int num = 100;
    IntPtr p = &num; // 等价于 int* p = &num;
    *p = 200;
    printf("num = %d\n", num); // 输出 200
    return 0;
}

b) 指向数组的指针

// 定义一个指向包含 5 个 int 的数组的指针类型
typedef int (*ARRAY_PTR_5)[5];
int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    ARRAY_PTR_5 p = &arr; // p 是一个指向数组的指针
    // 通过指针访问数组元素
    printf("p[0][2] = %d\n", p[0][2]); // 输出 30
    printf("(*p)[3] = %d\n", (*p)[3]); // 输出 40
    return 0;
}

c) 指向函数的指针

这是 typedef 最强大也最容易让人困惑的用法,没有 typedef,声明一个函数指针会非常冗长和复杂。

// 定义一个函数指针类型,该指针指向一个返回 int,参数为两个 int 的函数
typedef int (*CalcFunc)(int, int);
// 加法函数
int add(int a, int b) {
    return a + b;
}
// 减法函数
int subtract(int a, int b) {
    return a - b;
}
int main() {
    // 使用 CalcFunc 类型来声明函数指针变量
    CalcFunc func_ptr;
    func_ptr = add;
    printf("10 + 5 = %d\n", func_ptr(10, 5)); // 输出 15
    func_ptr = subtract;
    printf("10 - 5 = %d\n", func_ptr(10, 5)); // 输出 5
    return 0;
}

为结构体(struct)定义别名

这是 typedef 在结构体中的标准用法,可以避免每次使用结构体时都要写 struct 关键字。

先定义结构体,再用 typedef

struct Point {
    int x;
    int y;
};
// 为 struct Point 创建一个别名
typedef struct Point Point_t;
int main() {
    Point_t p1; // 现在可以直接使用 Point_t 定义变量,无需 struct
    p1.x = 10;
    p1.y = 20;
    printf("Point: (%d, %d)\n", p1.x, p1.y);
    return 0;
}

在定义结构体时同时定义别名(更常用)

这是一种更简洁的写法,将 structtypedef 合二为一。

// 注意:这里的 Point_t 是结构体类型的别名,而不是结构体标签
typedef struct {
    int x;
    int y;
} Point_t;
int main() {
    Point_t p1;
    p1.x = 10;
    p1.y = 20;
    printf("Point: (%d, %d)\n", p1.x, p1.y);
    // 这种写法下,下面这句代码是错误的,因为没有结构体标签 "Point"
    // struct Point p2; // Error: use of undeclared identifier 'Point'
    return 0;
}

补充说明:如果你希望同时保留结构体标签和别名,可以这样写:

typedef struct Point {
    int x;
    int y;
} Point_t;
// 现在两种方式都可以使用
Point_t p1;
struct Point p2;

为联合体(union)定义别名

语法与结构体完全相同。

typedef union {
    int i;
    float f;
} DataUnion;
int main() {
    DataUnion data;
    data.i = 10;
    printf("data.i = %d\n", data.i);
    data.f = 3.14f;
    printf("data.f = %f\n", data.f);
    return 0;
}

typedef#define 的区别

初学者很容易将 typedef#define 混淆,因为它们都可以用来创建别名,但它们有本质的区别:

特性 typedef #define
本质 关键字,由编译器处理。 宏定义,由预处理器在编译前处理。
机制 为一个类型创建一个别名,是文本替换。 进行简单的文本替换,不做语法检查。
作用域 遵循 C 语言的作用域规则(如在函数内定义则只在该函数内有效)。 从定义处到文件结尾都有效,没有作用域概念。
类型处理 理解类型,能处理指针、数组等复杂类型。 不理解类型,只是机械地替换文本。
示例 typedef int* IntPtr; #define IntPtr int*

一个经典的 #define 陷阱:

#define PTR_INT int*  // 这是一个宏定义
int a = 10, b = 20;
// 预处理后,这行代码会变成:int* p1, p2;
// p2 是一个 int 类型,而不是指针!
PTR_INT p1, p2; 
// 正确的 typedef 写法
typedef int* IntPtr;
IntPtr p3, p4; // p3 和 p4 都是指向 int 的指针

从这个例子可以看出,typedef 在处理指针等复杂类型时更安全、更可靠。


typedef 是 C 语言中一个非常有用的工具,它通过为现有类型创建别名,极大地提升了代码的可读性、简洁性和可维护性,无论是为基本类型、数组、指针还是自定义的结构体/联合体定义别名,typedef 都能发挥巨大作用,掌握 typedef,尤其是函数指针的 typedef,是迈向 C 语言高级编程的重要一步。

-- 展开阅读全文 --
头像
织梦安卓下载网模板哪里能下载?
« 上一篇 03-14
dede 4级导航如何正确显示?
下一篇 » 03-14

相关文章

取消
微信二维码
支付宝二维码

目录[+]