在 C 中命名类型时应使用什么样式

发布于 2024-08-16 05:20:36 字数 429 浏览 2 评论 0原文

根据 这个堆栈溢出答案,类型名称上的“_t”后缀在 C 中保留。当使用 typedef 创建新的不透明类型时,我习惯于在名称中包含某种指示:是一种类型。通常我会选择像 hashmap_t 这样的东西,但现在我需要别的东西。

C 中的类型有标准的命名方案吗?在其他语言中,像 Hashmap 这样使用 CapsCase 很常见,但我看到的很多 C 代码根本不使用大写。 CapsCase 也可以很好地与库前缀配合使用,例如 XYHashmap。

那么 C 中的类型命名是否有通用的规则或标准呢?

According to this stack overflow answer, the "_t" postfix on type names is reserved in C. When using typedef to create a new opaque type, I'm used to having some sort of indication in the name that this is a type. Normally I would go with something like hashmap_t but now I need something else.

Is there any standard naming scheme for types in C? In other languages, using CapsCase like Hashmap is common, but a lot of C code I see doesn't use upper case at all. CapsCase works fairly nicely with a library prefix too, like XYHashmap.

So is there a common rule or standard for naming types in C?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

疯狂的代价 2024-08-23 05:20:36

是的,如果您包含任何 POSIX 标头,POSIX 会保留以 _t 结尾的名称,因此理论上建议您远离这些标头。我从事的一个项目在过去二十年左右的时间里与此类名字发生了两三次冲突。您可以通过使用公司前缀(例如,您公司的 TLA 和下划线)或使用大小写混合名称(以及 _t 后缀)来最大程度地降低冲突风险;我见过的所有冲突都很短且全小写(dec_tloc_t,...)。

除了系统提供的(和系统保留的)_t 后缀之外,没有特定的广泛使用的约定。其中一种混合大小写系统(camelCase 或 InitialCaps)效果很好。系统前缀也很有效——更好的库往往会小心这些。

如果您决定使用小写字母和 _t 后缀,请确保使用足够长的名称,并根据 POSIX 标准、您使用的主要平台以及您认为可能的任何平台进行认真检查努力避免不必要的冲突。当您向客户发布一些名称example_t,然后发现在某些新平台上存在冲突时,最糟糕的问题就会出现。然后你必须考虑让客户更改他们的代码,而他们总是不愿意这样做。最好提前避免这个问题。

Yes, POSIX reserves names ending _t if you include any of the POSIX headers, so you are advised to stay clear of those - in theory. I work on a project that has run afoul of such names two or three times over the last twenty or so years. You can minimize the risk of collision by using a corporate prefix (your company's TLA and an underscore, for example), or by using mixed case names (as well as the _t suffix); all the collisions I've seen have been short and all-lower case (dec_t, loc_t, ...).

Other than the system-provided (and system-reserved) _t suffix, there is no specific widely used convention. One of the mixed-case systems (camelCase or InitialCaps) works well. A systematic prefix works well too - the better libraries tend to be careful about these.

If you do decide to use lower-case and _t suffix, do make sure that you use long enough names and check diligently against the POSIX standard, the primary platforms you work on, and any you think you might work on to avoid unnecessary conflicts. The worst problems come when you release some name example_t to customers and then find there is a conflict on some new platform. Then you have to think about making customers change their code, which they are always reluctant to do. It is better to avoid the problem up front.

撧情箌佬 2024-08-23 05:20:36

印第安山风格指南有一些建议:

个人项目无疑会有
他们自己的命名约定。那里
不过,有一些一般规则。

  • 带有前导和尾随下划线的名称是为系统保留的
    目的,并且不应该用于
    任何用户创建的名称。大多数系统
    使用它们作为用户的名称
    不应该知道。如果你必须
    拥有您自己的私人标识符,
    以一两个字母开头
    识别他们要发送到的包裹
    属于。

  • #define 常量应全部大写。

  • 枚举常量大写或全部大写

  • 函数、typedef 和变量名称,以及结构、联合和
    枚举标签名称应该位于较低的位置
    案例。

  • 许多宏“函数”全部大写。一些宏(例如 getchar 和
    putchar) 是小写的,因为它们
    也可以作为函数存在。
    小写宏名称仅
    如果宏的行为类似于
    函数调用,即它们评估
    他们的参数恰好一次并且做
    不给命名参数赋值。
    有时无法写出
    行为类似于函数的宏
    即使论据是
    仅评估一次。

  • 避免仅大小写不同的名称,例如 foo 和 Foo。相似地,
    避免 foobar 和 foo_bar。这
    造成混乱的可能性是
    相当大。

  • 同样,请避免使用看起来相似的名称。在许多终端和
    打印机,“l”、“1”和“I”看起来相当
    相似的。名为“l”的变量是
    特别糟糕,因为它看起来如此
    很像常量“1”。

一般来说,全局名称(包括
枚举)应该有一个共同的前缀
识别他们所使用的模块
属于.全局变量也可以
被分组到一个全局结构中。
类型定义的名称通常带有“_t”
附加在他们的名字后面。

避免可能与以下内容冲突的名称
各种标准库名称。一些
系统将包含更多库代码
比你想要的。另外,你的程序可能
有一天会延长。

The Indian Hill style guidelines have some suggestions:

Individual projects will no doubt have
their own naming conventions. There
are some general rules however.

  • Names with leading and trailing underscores are reserved for system
    purposes and should not be used for
    any user-created names. Most systems
    use them for names that the user
    should not have to know. If you must
    have your own private identifiers,
    begin them with a letter or two
    identifying the package to which they
    belong.

  • #define constants should be in all CAPS.

  • Enum constants are Capitalized or in all CAPS

  • Function, typedef, and variable names, as well as struct, union, and
    enum tag names should be in lower
    case.

  • Many macro "functions" are in all CAPS. Some macros (such as getchar and
    putchar) are in lower case since they
    may also exist as functions.
    Lower-case macro names are only
    acceptable if the macros behave like a
    function call, that is, they evaluate
    their parameters exactly once and do
    not assign values to named parameters.
    Sometimes it is impossible to write a
    macro that behaves like a function
    even though the arguments are
    evaluated exactly once.

  • Avoid names that differ only in case, like foo and Foo. Similarly,
    avoid foobar and foo_bar. The
    potential for confusion is
    considerable.

  • Similarly, avoid names that look like each other. On many terminals and
    printers, 'l', '1' and 'I' look quite
    similar. A variable named 'l' is
    particularly bad because it looks so
    much like the constant '1'.

In general, global names (including
enums) should have a common prefix
identifying the module that they
belong with. Globals may alternatively
be grouped in a global structure.
Typedeffed names often have "_t"
appended to their name.

Avoid names that might conflict with
various standard library names. Some
systems will include more library code
than you want. Also, your program may
be extended someday.

少女净妖师 2024-08-23 05:20:36

C 仅保留 _t 后缀的部分用途。据我所知,这只是当前以 _t 结尾的标识符加上以 intuint 开头的任何标识符(7.26.8)。然而,POSIX 可能会保留更多。

这是 C 中的一个普遍问题,因为你有非常扁平的命名空间,并且没有灵丹妙药。 如果您熟悉 CapCase 名称并且它们适合您,那么您应该继续使用它们。否则,您必须评估当前项目的目标并查看哪种解决方案最适合他们。

C only reserves some uses of a _t suffix. As far as I can tell, this is only current identifiers ending with _t plus any identifier that starts int or uint (7.26.8). However, POSIX may reserve more.

It's a general problem in C, since you have extremely flat namespaces, and there's no silver bullet. If you're familiar with CapCase names and they work well for you, then you should continue to use them. Otherwise, you'll have to evaluate the goals of the current project and see which solution best meets them.

另类 2024-08-23 05:20:36

CapsCase 通常用于 C 中的类型。

例如,如果您查看 GNOME 生态系统中的项目(GTK+、GDK、GLib、GObject、Clutter 等),您会看到类似 GtkButton 的类型或ClutterStageWindow。他们使用大写字母作为数据类型;函数名和变量都是小写并带有下划线分隔符 - 例如clutter_actor_get_geometry()

类型命名方案就像缩进约定 - 它们引发宗教战争,人们声称自己喜欢的方法具有某种道德优越感。遵循现有代码或相关项目中的风格(例如对我来说,过去几年的 GNOME)当然是更好的选择。

但是,如果您从头开始并且没有模板,那么就没有硬性规定规则。如果您对高效编码并在合理的时间下班以便回家喝杯啤酒或其他什么感兴趣,那么您当然应该选择一种风格并在您的项目中坚持使用它,但您选择哪种风格并不重要。

CapsCase is often used for types in C.

For instance, if you look at projects in the GNOME ecosystem (GTK+, GDK, GLib, GObject, Clutter, etc.), you'll see types like GtkButton or ClutterStageWindow. They only use CapsCase for data types; function names and variables are all lower-case with underscore separators - e.g. clutter_actor_get_geometry().

Type naming schemes are like indentation conventions - they generate religious wars with people asserting some sort of moral superiority for their preferred approach. It is certainly preferable to follow the style in existing code, or in related projects (e.g. for me, GNOME over the last few years.)

However, if you're starting from scratch and have no template, there's no hard-and-fast rule. If you're interested in coding efficiently and leaving work at reasonable hour so you can go home and have a beer or whatever, you certainly should pick a style and stick to it for your project, but it matters very little exactly which style you pick.

撞了怀 2024-08-23 05:20:36

一种效果相当好的替代解决方案是对所有类型名称和宏名称使用大写。全局变量可以是大写字母(CamelBack),所有局部变量可以是小写字母。

该技术有助于提高可读性,并利用语言语法减少变量名称中污染字符的数量;例如,gvar、kvar、type_t 等。例如,数据类型在语法上不能与任何其他类型混淆。

通过至少有一个大写字母,全局变量可以很容易地与局部变量区分开来。

我同意在所有标记名称中应避免使用前缀或后缀下划线。

让我们看下面的例子。

很明显,由于其案例,InvertedCount 是全局的。同样清楚的是,INT32U 和 RET_ERR 由于其语法而属于类型。同样清楚的是,INVERT_VAL() 是一个宏,因为它位于右侧,并且没有强制转换,因此它不能是数据类型。

但有一件事是肯定的。无论您使用哪种方法,它都应该符合您组织的编码标准。对我来说,杂乱越少越好。

当然,风格是另一个问题。

#define  INVERT_VAL(x)   (~x)
#define  CALIBRATED_VAL  100u

INT32U  InvertedCount;

typedef  enum {
    ERR_NONE = 0,
    ...
} RET_ERR;

RET_ERR  my_func (void) 
{
    INT32U  val;
    INT32U  check_sum;


    val           = CALIBRATED_VAL;   // --> Lower case local variable.
    check_sum     = INVERT_VAL(val);  // --> Clear use of macris.

    InvertedCount = checksum;         // --> Upper case global variable.  
                                      //     Looks different no g prefix required.

    ... 

    return (ERR_NONE); 
}

One alternate solution that works reasonably well is to use uppercase for all type names and macro names. Global variables may be CapCase (CamelBack) and all local variables lower case.

This technique helps to improve readability and also takes advantage of language syntax which reduces the number of pollution characters in variable names; e.g. gvar, kvar, type_t, etc. For example, data types cannot be syntatically confused with any other type.

Global variables are easily distinguished from locals by having at least one upper case letter.

I agree that prefixed or postfixed underscores should be avoided in all token names.

Lets look at the example below.

Its readily clear that InvertedCount is a global due to its case. It's equally clear that INT32U and RET_ERR are types due to their sytax. Its also clear that INVERT_VAL() is a macro due to the fact thats its on the right hand side and there is no cast so it cant be a data type.

One thing is for sure though. Whichever method you use, it should be inline with your organizations coding standard. For me, the least amount of clutter, the better.

Of course, style is a different issue.

#define  INVERT_VAL(x)   (~x)
#define  CALIBRATED_VAL  100u

INT32U  InvertedCount;

typedef  enum {
    ERR_NONE = 0,
    ...
} RET_ERR;

RET_ERR  my_func (void) 
{
    INT32U  val;
    INT32U  check_sum;


    val           = CALIBRATED_VAL;   // --> Lower case local variable.
    check_sum     = INVERT_VAL(val);  // --> Clear use of macris.

    InvertedCount = checksum;         // --> Upper case global variable.  
                                      //     Looks different no g prefix required.

    ... 

    return (ERR_NONE); 
}
茶色山野 2024-08-23 05:20:36

关于这个主题有很多想法和意见,但是没有一个通用的命名类型标准。最重要的是要保持一致。在缺乏编码标准的情况下,在维护代码时,请抵制使用其他命名约定的冲动。引入新的命名约定,即使它很完美,也会增加不必要的复杂性。

这实际上是采访人们时提出的一个很好的话题。我从来没有遇到过一个对此没有意见的优秀程序员。答案中没有意见或没有热情表明此人不是经验丰富的程序员。

There are many ideas and opinion on this subject, but there is no one universal standard for naming types. The most important thing is to be consistent. In the absence of coding standards, when maintaining code, resist the urge to use another naming convention. Introducing a new naming convention, even if it's perfect, can add unnecessary complexity.

This is actually a great topic to raise when interviewing people. I've never come across a good programmer that didn't have an opinion on this. No opinion or no passion in the answer indicates that the person isn't an experienced programmer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文