我们为什么需要在C中实例化枚举类型?

huangapple go评论113阅读模式
英文:

Why do we need instantation of enum type in C?

问题

我们假设在C代码中的主函数外声明了一个enum

我们可以在函数内部访问enum的成员而不会出现问题,也可以将其分配给int数据类型的变量。

但是,还存在enum类型的实例化概念,即

当使用int元素时为什么需要它?

我在主函数外部声明了这个:

enum months {Jan, Feb, Mar};

并在main()函数内部访问了它的成员使用int

int main () {
         int m=Feb;
         printf("%d", m);
}

(在屏幕上打印1)

但是在使用它的函数中创建enum类型的实例是很流行的:

int main () {
         enum months m=Feb;
         printf("%d", m);
}

(在屏幕上打印1)

当你可以使用int本身时,为什么需要这个呢?

英文:

Let's say we have a enum declared outside the main function in a C code.

We can access the members of the enum inside the function without issue, and also assign it to variables of int data type.

But, there exists the concept instantation of enum type, i.e.,

Why is it required when using enum elements with int also does the task?

I declared this outside the main function:

enum months {Jan, Feb, Mar};

..and accessed it's member(s) using int inside the main() function

int main () {
         int m=Feb;
         printf("%d", m);
}

(prints 1 on screen)

But it's popular to create an instance of the enum type in the function where it's used:

int main () {
         enum months m=Feb;
         printf("%d", m);
}

(prints 1 on screen)

Why is this needed when you can use int itself?

答案1

得分: 2

C在整体上具有相对较弱的类型安全性,特别是在处理枚举类型时,正如在这里解释的那样:https://stackoverflow.com/questions/43043246/how-to-create-type-safe-enums 正如该链接所示,枚举类型本质上只是高级的整数,特别是枚举常量,如 janfeb 等,它们实际上确实保证是 int 类型。

但是,我们可以使用 typedef enum 来实现稍微更好的类型安全性。尤其是在将枚举类型作为指针传递时,因为C对指针的类型安全性要比对普通整数类型要强得多。

示例:

typedef enum {Jan=1, Feb, Mar} months;

void print_month (const months* m)
{
  printf("%d\n", *m);
}

int main () {
    months m=Feb;
    print_month(&m); // ok

    int n=Feb;
    print_month(&n); // compiler error
}

(确保以严格的C编译并启用最大警告:什么编译选项适合初学C的人?)

英文:

C has rather weak type safety overall, especially when it comes to enums as explained here: https://stackoverflow.com/questions/43043246/how-to-create-type-safe-enums As shown in that link, enums are essentially just glorified integers, especially enumeration constants, jan feb etc which are actually guaranteed to be of type int.

but we can use typedef enum to achieve slightly better type safety. Namely when passing enums as pointers, because C has much stronger type safety for pointers than for plain integer types.

Example:

typedef enum {Jan=1, Feb, Mar} months;

void print_month (const months* m)
{
  printf("%d\n", *m);
}

int main () {
    months m=Feb;
    print_month(&m); // ok

    int n=Feb;
    print_month(&n); // compiler error
}

(Make sure to compile as strict C with max warnings: What compiler options are recommended for beginners learning C?)

答案2

得分: 0

如果您使用int,那么它就不是enum类型,就像使用float来表示int一样,虽然可以使用,但是不够具体,会丢失信息。

int main () {
         int m=Feb;
         printf("%d", m);
}

在这里,变量m的类型是int。在main函数的第一行中,发生了从enum monthsint的隐式转换。无论您在哪里使用m,它都会作为int工作。

int main () {
         enum months m=Feb;
         printf("%d", m);
}

而在第二种情况下,类型是enum months。转换发生在调用printf时。

希望这有所帮助。

英文:

If you use int, then it's simply not enum type, it's like using float for int, you can use but it's less specific and loses information.

int main () {
         int m=Feb;
         printf("%d", m);
}

Here, type of m is int. In first line of main function, there is implicit casting involved from enum months to int. Wherever you will use m it will work as int.

int main () {
         enum months m=Feb;
         printf("%d", m);
}

While in second case, type is enum months. Casting happens when you call printf.

Hope this helps.

答案3

得分: 0

"Instantiation" 是创建特定类型的实际变量(实例)的过程。在这个示例中,您可以选择创建枚举类型 months 的本地实例,或者创建一个 int 类型的实例,它对月份的名称一无所知,但仍然可以保存 enum month 变量用来表示月份的底层数字。

虽然在运行时 enum 被编译为 int,但 enum 为我们的源代码添加了一层抽象,使人更容易理解。当处理一组有限的有效值,每个值代表不同的含义时,我们使用 enum 类型。使用它们是为了对未来的自己友好,因为C语言允许你做各种可能会在后来造成问题的事情;Ben Klemens(参见资源)将C描述为"朋克摇滚"!

人们比编译器更频繁地阅读源代码,尤其是在团队中工作时。使用 enum 类型使代码更清晰,以便您和您的同事能够理解代码的意图。编译器不知道您的代码打算做什么 - 它只是按照指示执行 - 但对您作为开发人员来说,这真的很重要。

当您利用类型系统时,您正在使开发人员更容易理解和维护代码。即使是独立开发者也会从中受益,因为您很快会忘记自己的实现细节。通过为变量和函数选择有意义的名称,您给自己提供了线索,就像使用 enum 时一样。此外,enum 告诉编译器哪些有限的值对于该类型的变量是可以的,从而使它有机会在编译时捕获到错误的值,而不是在运行时失败。

注意事项

在C中,您仍然需要明确检查无效值,例如在 switch 语句中使用 default 子句,特别是如果您对 enum 进行任何算术运算。

Ben Klemens 对C如何处理 enum 类型并不完全没有批评,尤其是对于混乱编译器的全局命名空间,从而需要更长、更笨重的标识符以避免在较大的程序中发生名称冲突。

资源

S. McConnell, Code complete: a practical handbook of software construction. Redmond, Wash: Microsoft Press, 1993.

B. Klemens, 21st century C, Second edition. Beijing ; Sebastopol, CA: O’Reilly Media, Inc, 2014.

搜索关键词 C "code quality"C "best practice"

此外,一定要查看 https://stackoverflow.com/questions/1262459/coding-standards-for-pure-c-not-c 这个网站上的内容。

英文:

Instantiation is the creation of an actual variable (an instance) of a particular type. In the example, you choose to either create a local instance of the enumerated type, months, or an instance of an int type, which knows nothing about the names of months, but can still hold the underlying number that enum month variables use to represent months.

While it's true that enums are compiled to ints at runtime, enums add a layer of abstraction to our source-code that makes it easier for humans to understand. We use enum types when dealing with a limited set of valid values, each representing a different meaning. Using them is all about being nice to your future self, because C gives you free rein to do all sorts of things that might hurt later; Ben Klemens (see Resources) describes C as "Punk Rock"!

Humans read source code more frequently than the compiler does, especially when you work in a team. Using enum types makes the code clearer, so that you and your colleagues can understand the intent of the code. The compiler doesn't know about what your code is intended to do - it just does as it's told - but it really matters to you, the developer.

When you make use of the type system, you're making it easier for developers to understand and maintain the code. Even solo developers benefit from this, because you soon forget the details of your implementation. You're doing a favor to the future-you, by giving yourself a clue, just like when you choose meaningful names for your variables and functions. Also, enums tell the compiler which limited set of values are okay for variables of that type, thus giving it a chance to catch mistyped values at compile time, rather than failing at runtime.

Caveats

With C, you still need to explicitly check for invalid values, eg. in a switch statement with a default clause, especially if you do any arithmetic on the enum.

Ben Klemens is not entirely uncritical of how C handles enum types, especially for cluttering the compiler's global namespace, thereby requiring longer, clunkier identifiers to avoid name clashes in larger programs.

Resources

S. McConnell, Code complete: a practical handbook of software construction. Redmond, Wash: Microsoft Press, 1993.

B. Klemens, 21st century C, Second edition. Beijing ; Sebastopol, CA: O’Reilly Media, Inc, 2014.

Search terms C "code quality" or C "best practice".

Also, definitely check out https://stackoverflow.com/questions/1262459/coding-standards-for-pure-c-not-c on this site.

huangapple
  • 本文由 发表于 2023年6月22日 12:18:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76528577.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定