typedef在c语言中的作用,为什么要在C语言中这么频繁地对结构进行typedef?

我看过很多程序,其中包括以下结构

typedef struct

{

int i;

char k;

} elem;

elem user;

为什么经常需要它? 有任何特定原因或适用范围?

#1楼

Linux内核编码样式第5章给出了使用typedef优缺点(主要是缺点)。

请不要使用“ vps_t”之类的东西。

对结构和指针使用typedef是错误的 。 当你看到一个

vps_t a;

在源代码中是什么意思?

相反,如果说

struct virtual_container *a;

您实际上可以说出“ a”是什么。

许多人认为typedef是“帮助可读性”。 不是这样 它们仅对以下有用:

(a)完全不透明的对象(使用typedef主动隐藏该对象是什么)。

例如:“ pte_t”等不透明对象,您只能使用适当的访问器函数来访问。

注意! 不透明和“访问器功能”本身不好。 之所以将它们用于pte_t等之类,是因为那里确实存在绝对零的可访问信息。

(b)清除整数类型,其中抽象有助于避免混淆,无论是“ int”还是“ long”。

u8 / u16 / u32是完美的typedef,尽管它们比这里更适合(d)类。

注意! 再次-需要有一个原因 。 如果某事是“无符号的长”,则没有理由这样做

typedef unsigned long myflags_t;

但是,如果有明确的原因说明为什么在某些情况下它可能是“ unsigned int”而在其他配置下可能是“ unsigned long”,则一定要继续使用typedef。

(c)当您使用稀疏从字面上创建用于类型检查的新类型时。

(d)在某些特殊情况下,与标准C99类型相同的新类型。

尽管眼睛和大脑只需要很短的时间就习惯了'uint32_t'这样的标准类型,但是仍然有人反对使用它们。

因此,允许使用特定于Linux的'u8 / u16 / u32 / u64'类型及其与标准类型相同的带符号等效项-尽管在您自己的新代码中不是强制性的。

编辑已使用一种或另一组类型的现有代码时,应遵循该代码中的现有选择。

(e)在用户空间中可以安全使用的类型。

在用户空间可见的某些结构中,我们不能要求C99类型,也不能使用上面的“ u32”形式。 因此,我们在与用户空间共享的所有结构中使用__u32和类似类型。

也许还有其他情况,但是该规则基本上应该是从不使用typedef,除非您可以清楚地匹配这些规则之一。

通常,指针或具有可以合理地直接访问的元素的结构永远都不应该是typedef。

#2楼

事实证明,这是有利有弊的。 有用的信息来源是开创性的书“ Expert C Programming”( 第3章 )。 简而言之,在C中,您具有多个名称空间: 标签,类型,成员名称和标识符 。 typedef为类型引入别名,并将其定位在标记名称空间中。 即

typedef struct Tag{

...members...

}Type;

定义了两件事。 标签名称空间中的一个标签,类型名称空间中的一个类型。 所以,你都可以做Type myType和struct Tag myTagType 。 诸如struct Type myType Tag myTagType或Tag myTagType是非法的。 另外,在这样的声明中:

typedef Type *Type_ptr;

我们定义一个指向类型的指针。 因此,如果我们声明:

Type_ptr var1, var2;

struct Tag *myTagType1, myTagType2;

然后var1 , var2和myTagType1是指向Type的指针,而myTagType2不是。

在上面提到的书中,提到类型定义结构不是很有用,因为它仅使程序员不必编写struct这个词。 但是,与许多其他C程序员一样,我也有反对意见。 虽然有时要混淆一些名称(这就是为什么在诸如内核之类的大型代码库中不建议使用它的原因),但是当您要在C中实现多态时,它可以在此处帮助查找详细信息 。 例:

typedef struct MyWriter_t{

MyPipe super;

MyQueue relative;

uint32_t flags;

...

}MyWriter;

你可以做:

void my_writer_func(MyPipe *s)

{

MyWriter *self = (MyWriter *) s;

uint32_t myFlags = self->flags;

...

}

因此,您可以通过强制转换通过内部结构( MyPipe )访问外部成员( flags )。 对我来说, (struct MyWriter_ *) s;整个类型比做(struct MyWriter_ *) s;容易混淆(struct MyWriter_ *) s; 每次您想要执行此类功能时。 在这些情况下,简短引用是一件很重要的事情,特别是如果您在代码中大量使用该技术的话。

最后,随着最后一个方面typedef ED类型是无法扩展它们,而相比之下,宏。 例如,如果您有:

#define X char[10] or

typedef char Y[10]

然后您可以声明

unsigned X x; but not

unsigned Y y;

我们并不真正在意此结构,因为它不适用于存储说明符( volatile和const )。

#3楼

完全,在C语言中,struct / union / enum是由C语言预处理器处理的宏指令(不要误以为处理“ #include”和其他的预处理器)

所以:

struct a

{

int i;

};

struct b

{

struct a;

int i;

int j;

};

struct b被扩展为如下形式:

struct b

{

struct a

{

int i;

};

int i;

int j;

}

因此,在编译时,它在堆栈上的演变如下:b:int ai int i int j

这也是为什么很难拥有自引用结构的原因,C预处理程序在无法终止的声明循环中进行处理。

typedef是类型说明符,这意味着只有C编译器对其进行处理,并且可以像他想要的那样优化汇编程序代码实现。 它也不会像préprocessor那样愚蠢地使用par类型的成员来处理结构,而是使用更复杂的引用构造算法,因此构造如下:

typedef struct a A; //anticipated declaration for member declaration

typedef struct a //Implemented declaration

{

A* b; // member declaration

}A;

被允许并且功能齐全。 当执行线程离开初始化函数的应用程序字段时,此实现还可以访问编译器类型转换并消除一些错误影响。

这意味着在C中,typedef更像C ++类,而不是孤独的结构。

#4楼

使用typedef可以避免每次声明该类型的变量时都必须编写struct :

struct elem

{

int i;

char k;

};

elem user; // compile error!

struct elem user; // this is correct

#5楼

正如Greg Hewgill所说,typedef意味着您不再需要到处编写struct 。 这不仅可以节省击键次数,而且还可以使代码更整洁,因为它提供了更多的smidgen抽象。

像东西

typedef struct {

int x, y;

} Point;

Point point_new(int x, int y)

{

Point a;

a.x = x;

a.y = y;

return a;

}

当您不需要在所有地方都看到“ struct”关键字时,它会变得更加干净,看起来好像您的语言中确实存在一个名为“ Point”的类型。 在typedef ,我猜是这样。

还要注意,尽管您的示例(和我的示例)省略了对struct本身的命名,但实际上,为要提供不透明的类型命名也很有用。 然后,您将在标题中包含以下代码,例如:

typedef struct Point Point;

Point * point_new(int x, int y);

然后在实现文件中提供struct定义:

struct Point

{

int x, y;

};

Point * point_new(int x, int y)

{

Point *p;

if((p = malloc(sizeof *p)) != NULL)

{

p->x = x;

p->y = y;

}

return p;

}

在后一种情况下,您无法返回“按值”,因为头文件的用户不知道其定义。 例如,这是GTK +中广泛使用的技术。

UPDATE请注意,在一些C项目中,使用typedef隐藏struct被认为是一个坏主意,Linux内核可能是最著名的此类项目。 有关Linus的愤怒话,请参阅Linux Kernel CodingStyle文档的第5章。 :)我的意思是,毕竟问题中的“应该”可能不是一成不变的。

来源:oschina

链接:https://my.oschina.net/stackoom/blog/3167258

<think> 首先,用户的问题是:“我想了解typedef在C语言中的作用”,直接询问typedef在C语言中的作用。 从系统指令看: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 用户提供了几个引用: - 引用[1]: 解释了typedef的基本用法:为现有数据类型创建新名字,方便阅读和理解。 - 引用[2]: 强调了typedef在C语言中的实用性,可以简化复杂类型声明。 - 引用[3]: 对比了typedef和#define的区别,指出typedef是为类型起新名字,而#define是简单字符串替换。 - 引用[4]: 讨论了typedef在确保类型可移植性方面的作用。 我需要基于这些引用构建回答,但用户说“上述引用仅供参考,并不是用户真正的需求”,并提示“请尽可能多的参考用户上一次的问题和你的回答”。回顾对话历史: - 初始系统指令是关于数学表达式和代码格式的。 - 用户上一次的问题是:"参考站内引用:引用[1]:...等",然后直接问"我想了解typedef在C语言中的作用"。 - 之前的对话中,我没有回答过这个问题,这是第一次用户问这个问题。所以,没有“上一次的问题和回答”可以参考。用户的上一条消息就是这个问题。 因此,我应该直接回答用户的问题,结合提供的引用信息。 结构化回答: 1. **简述typedef作用**:解释typedef是什么及其基本目的。 2. **详细描述作用和用法**:覆盖基本用法、简化复杂类型、typedef vs #define、可移植性等。 3. **使用示例代码**:系统指令要求代码块,用户示例中显示了Python代码,所以我可以添加C语言代码示例。 4. **添加引用标识**:在回答中自然添加引用标识,如[^1],基于提供的引用。 5. **生成相关问题**:在结束时生成几个相关问题。 回答结构: - 开头简要介绍。 - 主体部分分点解释。 - 结尾生成相关问题。 确保中文回答。 关键点从引用中提炼: - 基本用法:typedef 原有类型名 新的类型名; [^1] - 作用:使代码易读、理解[^1],简化复杂类型[^2] - typedef vs #define:举例说明,typedef定义类型别名,#define是宏替换[^3] - 可移植性:确保类型一致性[^4] 添加自己的知识:typedef常用于结构体、指针等,以使代码更清晰。 代码示例:可以添加一个示例代码块,展示typedef的使用。 生成相关问题:类似示例中的,如"typedef和#define的区别?"、"typedef结构中的应用?"等。 最终回答结构: 1. 引言:typedef的定义和作用。 2. 主要作用: - 提高可读性 - 简化复杂类型 - 确保可移植性 - 与#define的区别 3. 代码示例。 4. 引用标识添加。 5. 生成相关问题。 </think> ### typedef在C语言中的作用 在C语言中,`typedef`是一个关键字,主要用于为现有数据类型(如`int`、`char`、`float`等)创建新的别名(也称为类型别名)。这一特性可以显著提升代码的可读性、可维护性和可移植性,尤其在处理复杂类型(如指针、数组、结构体)时非常实用。下面我将逐步解释其核心作用,并辅以代码示例进行说明。 #### 1. **提高代码可读性和理解性** `typedef`允许程序员为复杂的原始类型定义更具描述性的名称。例如,直接使用`int`定义年龄变量可能不够清晰,但通过`typedef`定义一个别名如`Age`,代码意图一目了然[^1]。 - **基本语法**:`typedef 原始类型名 新类型名;` - **示例**: ```c typedef int Age; // 定义一个Age类型,实际为int Age studentAge = 20; // 使用Age类型声明变量,比直接用int更易读 ``` 这样,`Age`直接表示了变量的含义,避免了代码中出现大量“魔法数字”或模糊的类型声明。 #### 2. **简化复杂类型的声明** 在处理指针、数组或嵌套结构时,原始语法可能很冗长。`typedef`可以简化这些声明,使代码更简洁[^2]。 - **指针类型简化**: ```c typedef char* String; // 定义一个String类型,实际为char指针 String name = "Alice"; // 声明字符串变量更直观 ``` - **结构体简化**: ```c typedef struct { int x; int y; } Point; // 定义Point结构体类型 Point p1 = {10, 20}; // 直接使用Point声明变量,无需重复写struct关键字 ``` 这减少了代码冗余,尤其在大型项目中更容易维护。 #### 3. **提升代码可移植性** 不同的编译器或平台可能对某些类型(如`short int`)的尺寸或语义有差异。`typedef`可以通过统一别名来屏蔽这些差异,确保代码在不同环境下行为一致[^4]。 - **示例**: ```c typedef short int Int16; // 确保Int16始终是16位整数 Int16 value = 100; // 在跨平台代码中使用Int16,避免编译器差异 ``` 这在嵌入式系统或跨平台开发中尤为重要。 #### 4. **与宏定义(#define)的区别** `typedef`是类型别名机制,而`#define`是预处理器指令,仅进行字符串替换。这可能导致意外行为,尤其在处理指针或复杂声明时[^3]。 - **对比示例**: ```c typedef char* pStr1; // 定义类型别名pStr1为char指针 #define pStr2 char* // 宏定义简单替换 pStr1 s1, s2; // s1和s2都是char指针 pStr2 s3, s4; // s3是char指针,s4是char(宏替换后变为 char* s3, s4;) ``` 这里,`typedef`确保了`s1`和`s2`都是指针类型,而`#define`仅替换字符串,导致`s4`不是指针。因此,`typedef`在类型安全性上更可靠。 总之,`typedef`的核心作用是通过创建类型别名,优化代码的清晰度、简洁性和可移植性。在实际编程中,它常用于定义数据结构、函数指针或平台相关类型。对于深入学习,请参阅C语言标准文档或权威教程[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值