在上面提到的书中,它提到typedefing结构不是很有用,因为它只会使程序员不会编写单词struct . 但是,我和许多其他C程序员一样有异议 . 虽然它有时会变得混淆一些名字(这就是为什么它不是当你想在C中实现多态时,建议在大型代码库(如内核)中它有很大的帮助look here for details . 例:
struct complex{ int real_part, img_part }COMPLEX;
main(){
struct KOMPLEKS number; // number type is now a struct type
number.real_part = 3;
number.img_part = -1;
printf("Number: %d.%d i \n",number.real_part, number.img_part);
}
typedef struct complex{int real_part, img_part; }COMPLEX;
//now COMPLEX is the new name for this structure and if I want to use it without
// a keyword like in the first example 'struct complex number'.
main(){
COMPLEX number; // number is now the same type as in the first example
number.real_part = 1;
number.img)part = 5;
printf("%d %d \n", number.real_part, number.img_part);
}
如果您有一些将在整个程序中使用的本地对象(结构,数组,有 Value ),您只需使用'typedef'为其命名即可 .
15 回答
总之,在C语言中,struct / union / enum是由C语言预处理器处理的宏指令(不要误认为处理“#include”和其他的预处理器)
所以:
struct b被用作这样的东西:
所以,在编译时它会在堆栈上演变为:b:int ai int i int j
这也是为什么拥有自发结构的难以理解的原因,C预处理器在无法终止的释放循环中进行循环 .
typedef是类型说明符,这意味着只有C编译器处理它,它可以像他想要的那样优化汇编程序代码实现 . 它也不会像préprocessor那样愚蠢地使用类型的成员使用结构但是使用更复杂的参考构造算法,所以构造如:
被授予并且功能齐全 . 此实现还允许访问编译器类型转换,并在执行线程离开初始化函数的应用程序字段时删除一些窃听效果 .
这意味着在C typedef中,C类比孤独的结构更接近 .
正如Greg Hewgill所说,typedef意味着你不再需要在整个地方写出
struct
. 这不仅可以节省击键次数,还可以使代码更清晰,因为它提供了更多抽象的smidgen .好像的东西
当您不需要在整个地方看到"struct"关键字时,它变得更干净,它看起来更像是您的语言中确实存在一个名为"Point"的类型 . 在
typedef
之后,我猜是这样的 .另请注意,虽然您的示例(和我的)省略了命名
struct
本身,但实际命名它对于您想要提供opaque类型时也很有用 . 然后你在 Headers 中有这样的代码,例如:然后在实现文件中提供
struct
定义:在后一种情况下,您不能返回Point by值,因为它的定义对头文件的用户是隐藏的 . 例如,这是一种在_790778中广泛使用的技术 .
UPDATE 请注意,还有一些备受推崇的C项目,其中使用
typedef
隐藏struct
被认为是一个坏主意,Linux内核可能是最知名的此类项目 . 对于Linus的愤怒话语,请参阅The Linux Kernel CodingStyle document的第5章 . :)我的观点是,问题中的_790783可能并非一成不变 .令人惊讶的是,有多少人犯了这个错误 . 请不要在C中使用typedef结构,它会不必要地污染全局命名空间,这通常在大型C程序中已经被污染了 .
此外,没有标记名称的typedef'd结构是导致头文件之间不必要的排序关系的主要原因 .
考虑:
有了这样的定义,不使用typedef,compiland单元可以包含foo.h来获得
FOO_DEF
定义 . 如果它不是foo
结构的foo
成员,则不需要包含"bar.h"文件 .此外,由于标记名称和成员名称之间的名称空间不同,因此可以编写非常易读的代码,例如:
由于命名空间是独立的,因此命名变量与其struct标记名称不一致 .
如果我必须维护你的代码,我将删除你的typedef结构 .
来自Dan Saks的一篇旧文章(http://www.ddj.com/cpp/184403396?pgno=3):
链接的文章还讨论了不需要
typedef
的C行为如何导致细微的名称隐藏问题 . 为了防止出现这些问题,尽管乍一看似乎没必要,但是你也可以在C语言中使用你的类和结构 . 在C中,使用typedef
名称隐藏成为编译器告诉您的错误,而不是隐藏的潜在问题源 .使用
typedef
避免每次声明该类型的变量时都必须编写struct
:总是输入定义枚举和结构的另一个好理由是这个问题的结果:
注意结构中EnumDef中的拼写错误(Enu u mDef)?这编译没有错误(或警告),并且(取决于C标准的字面解释)是正确的 . 问题是我刚刚在我的struct中创建了一个新的(空)枚举定义 . 我不是(按预期)使用先前的定义EnumDef .
使用typdef类似的拼写错误会导致使用未知类型的编译器错误:
我会提倡ALWAYS typedef'ing结构和枚举 .
不仅要节省一些打字(没有双关语;)),而是因为它更安全 .
Linux kernel coding style第5章给出了使用
typedef
的优点和缺点(主要是利弊) .我不认为使用typedef可以进行前向声明 . 使用struct,enum和union允许在依赖(知道)是双向时转发声明 .
风格:在C中使用typedef非常有意义 . 处理需要多个和/或可变参数的模板时几乎是必要的 . typedef有助于保持命名直线 .
在C编程语言中并非如此 . 使用typedef最常见的目的不是为了混淆数据结构的使用 . 由于只有{struct(6),enum(4),union(5)}数量的击键用于声明数据类型,因此几乎没有用于结构的别名 . 该数据类型是联合或结构吗?使用简单的非typdefed声明可以让您立即知道它是什么类型 .
注意如何编写Linux,严格避免使用这种别名的废话类型 . 结果是简约而干净的风格 .
事实证明,有利有弊 . 一个有用的信息来源是开创性的书"Expert C Programming"(Chapter 3) . 简而言之,在C中,您有多个名称空间: tags, types, member names and identifiers .
typedef
为类型引入了别名,并将其定位在标记名称空间中 . 也就是说,定义了两件事 . 标记命名空间中的一个标记和类型命名空间中的一个类型 . 所以你可以同时做
Type myType
和struct Tag myTagType
. 像struct Type myType
或Tag myTagType
这样的声明是非法的 . 另外,在这样的声明中:我们定义了一个指向Type的指针 . 所以,如果我们宣布:
那么
var1
,var2
和myTagType1
是Type的指针,但myTagType2
不是 .在上面提到的书中,它提到typedefing结构不是很有用,因为它只会使程序员不会编写单词struct . 但是,我和许多其他C程序员一样有异议 . 虽然它有时会变得混淆一些名字(这就是为什么它不是当你想在C中实现多态时,建议在大型代码库(如内核)中它有很大的帮助look here for details . 例:
你可以做:
因此,您可以通过内部结构(
MyPipe
)通过强制转换访问外部成员(flags
) . 对我来说,每次想要执行这样的功能时,抛出整个类型比做(struct MyWriter_ *) s;
更容易混淆 . 在这些情况下,简短的引用是一个大问题,特别是如果您在代码中大量使用该技术 .最后,与宏相比,使用
typedef
ed类型的最后一个方面是无法扩展它们 . 例如,您有:然后你可以申报
我们并不关心结构,因为它不适用于存储说明符(
volatile
和const
) .让我们从基础知识入手,继续努力 .
以下是结构定义的示例:
这里名称
point
是可选的 .结构可以在定义期间或之后声明 .
在定义期间声明
定义后声明
现在,仔细注意上面的最后一个案例;如果您决定在代码中稍后创建该类型,则需要编写
struct point
来声明该类型的结构 .输入
typedef
. 如果您打算稍后在程序中使用相同的蓝图创建新结构(结构是自定义数据类型),则在定义期间使用typedef
可能是个好主意,因为您可以保存一些前进的输入 .命名自定义类型时要小心
没有什么可以阻止您在自定义类型名称的末尾使用_t后缀,但POSIX标准保留使用后缀_t来表示标准库类型名称 .
您(可选)给出结构的名称称为标记名称,如上所述,它本身不是一个类型 . 要获取该类型需要struct前缀 .
抛开GTK,我不确定标记名是否与结构类型的typedef一样常用,所以在C中可以识别并且你可以省略struct关键字并使用标记名作为类型名称:
typedef不会提供一组相互依赖的数据结构 . 这与typdef无法做到:
当然你可以随时添加:
究竟是什么意思呢?
A> a typdef通过允许 creation of more meaningful synonyms for data types 来帮助程序的含义和文档 . 此外,它们还有助于针对可移植性问题参数化程序(K&R,pg147,C prog lang) .
B> a structure defines a type . Structs允许方便地对一组变量进行分组,以便于处理(K&R,pg127,C prog lang . )作为一个单元
C> typedef结构在上面的A中解释 .
D>对我来说,结构是自定义类型或容器或集合或名称空间或复杂类型,而typdef只是创建更多昵称的一种方法 .
结果是C99 typedef是必需的 . 它已经过时了,但很多工具(ala HackRank)使用c99作为其纯C实现 . 那里需要typedef .
我不是说他们应该改变(可能有两个C选项)如果要求改变了,我们这些在网站上接受采访的人将是SOL .
在'C'编程语言中,关键字'typedef'用于为某个对象(struct,array,function..enum类型)声明一个新名称 . 例如,我将使用'struct-s' . 在'C'中,我们经常在'main'函数之外声明'struct' . 例如:
每次我决定使用结构类型时,我都需要这个关键字'struct'是''name' . 'typedef'将只重命名该类型,我可以在我的程序中每次使用时都使用该新名称 . 所以我们的代码将是:
如果您有一些将在整个程序中使用的本地对象(结构,数组,有 Value ),您只需使用'typedef'为其命名即可 .