为什么C程序员使用typedef重命名基本类型?

时间:2010-07-27 04:57:05

标签: c++ c

所以我远不是C的专家,但是有些东西一直困扰着我长时间阅读的代码:有人可以向我解释为什么C(++)程序员使用typedef重命名简单类型吗?我理解为什么你会将它们用于结构体,但我认为是什么原因的确切原因是

typedef unsigned char uch;
typedef uch UBYTE;
typedef unsigned long ulg;
typedef unsigned int u32;
typedef signed short s16;

这对我来说是否有一些优势(一个程序员,他的经验始于Java并且没有在严格的类型安全语言之外进行过远)?因为我无法想到它的任何原因 - 看起来它只会使不熟悉项目的人的代码不那么可读。

随意像对待C新手一样对待我,老实说我对此知之甚少,而且很可能从一开始我就误解了。 ;)

9 个答案:

答案 0 :(得分:77)

重命名类型而不更改其公开的语义/特征没有多大意义。在你的例子中

typedef unsigned char uch;
typedef unsigned long ulg;

属于该类别。除了简短的名字外,我没有看到这一点。

但是这些

typedef uch UBYTE;
typedef unsigned int u32;
typedef signed short s16;

是一个完全不同的故事。例如,s16代表“带符号的16位类型”。此类型不一定是signed short。隐藏在s16后面的特定类型取决于平台。程序员引入了这种额外级别的命名间接,以简化对多个平台的支持。如果在某个其他平台上签名的16位类型恰好是signed int,程序员只需要更改一个typedef定义。 UBYTE显然代表无符号机器字节类型,不一定是unsigned char

值得注意的是,C99规范已经为特定宽度的整数类型提供了标准命名法,例如int16_tuint32_t等。在不支持C99的平台上坚持使用这种标准命名约定可能更有意义。

答案 1 :(得分:14)

这允许便携性。例如,您需要一个无符号的32位整数类型。这是哪种标准类型?你不知道 - 它是实现定义的。这就是为什么你typedef一个单独的类型是32位无符号整数并在你的代码中使用新类型。当您需要在另一个C实现上进行编译时,您只需更改typedef s。

答案 2 :(得分:8)

有时,它会用于将volatile unsigned long等笨重的东西缩小为更紧凑的内容,例如vuint32_t

其他时候,它有助于提高可移植性,因为int之类的类型在每个平台上并不总是相同。通过使用typedef,您可以将您感兴趣的存储类设置为平台最接近的匹配,而无需更改所有源代码。

答案 3 :(得分:4)

以下是C编程语言(K& R)的引用

  

除了纯粹的审美问题外,使用有两个主要原因   类型定义。

首先参数化程序

  

首先是针对可移植性问题参数化程序。   如果typedef用于数据类型   这可能只取决于机器   当typedef需要改变时   程序被移动了。

     

一种常见的情况是对各种整数使用typedef名称   数量,然后做出适当的   short,int和long的选择集   对于每台主机。类似的   标准库中的size_t和ptrdiff_t就是例子。

斜体部分告诉我们程序员typedef基本类型的可移植性。如果我想确保我的程序在不同的平台上工作,使用不同的编译器,我将尽力确保其可行的可移植性,typedef就是其中之一。

当我在Windows平台上使用Turbo C编译器开始编程时,它给我们的大小为int 2.当我转移到Linux平台和GCC编译器时,我得到的大小是4.如果我开发了使用Turbo C的程序依赖于sizeof( int )始终为2的断言,它将无法正确移植到我的新平台。

希望它有所帮助。

以下来自K& R的报价与您的查询无关,但我也是为了完成而发布的。

第二 - 提供更好的文档

  

typedef的第二个目的是为a提供更好的文档   程序 - 一个名为Treeptr的类型可能比仅仅声明为一个类型更容易理解   指向复杂结构的指针。

答案 4 :(得分:3)

它有很多原因。我的想法是:

  1. Typename变得更短,因此代码也更小,更易读。
  2. 较长结构名称的别名效果。
  3. 特定团队/公司/风格使用的约定。
  4. 移植 - 在所有操作系统和机器上具有相同的名称。它的原生数据结构可能略有不同。

答案 5 :(得分:3)

这些模式中的大多数是通过读取和复制现有错误代码而产生的不良做法。他们常常反映出对C所做或不需要的误解。

  1. 类似于#define BEGIN {,除了它可以节省一些打字而不是赚取更多。
  2. 类似于#define FALSE 0。如果您对“byte”的想法是最小的可寻址单元,char是按字节定义的字节。如果您对“byte”的想法是一个八位字节,那么char是八位字节类型,或者您的机器没有八位字节类型。
  3. 对于那些无法触摸类型的人来说,这是一个非常难看的简写......
  4. 是个错误。它应该是typedef uint32_t u32;或更好,uint32_t应该直接使用。
  5. 与4.相同。将uint32_t替换为int16_t
  6. 请在其上加上“被视为有害”标记。当您真正需要创建一个新类型时,应该使用typedef,该类型的定义可能会在代码的生命周期中发生变化,或者当代码被移植到不同的硬件时,而不是因为您认为C会更“漂亮”而不同输入姓名。

答案 6 :(得分:0)

我们使用它来使项目/平台特定,一切都有一个共同的命名约定

pname_int32, pname_uint32, pname_uint8 - pname是项目/平台/模块名称

还有一些#defines

pname_malloc, pname_strlen

更容易阅读并缩短像unsname char这样的长数据类型到pname_uint8,这也使它成为所有模块的约定。

移植时,您只需修改单个文件,从而轻松实现移植。

答案 7 :(得分:0)

长话短说, 您可能希望这样做以使您的代码可移植(省力/编辑)。 这样你就不依赖于'int',而是使用INTEGER,它可以是你想要的任何东西。

答案 8 :(得分:0)

所有[|u]intN_t类型,其中N = 8 | 16 | 32 | 64等等,按照这种精确的方式为每个体系结构定义。这是标准没有强制要求charintfloat等具有N位的事实的直接后果 - 这将是疯狂的。相反,标准将每种类型的最小值和最大值定义为程序员的保证,并且在各种体系结构类型中可能会超出这些边界。这不是一个罕见的景象。

您的帖子中的typedef用于定义特定体系结构中特定长度的类型。它可能不是命名的最佳选择;在我看来,u32s16有点太短了。此外,公开名称ulguch是一件坏事,可以为它们添加特定于应用程序的字符串,因为它们显然不会被公开。

希望这有帮助。