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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值