在 C 中强制执行强类型检查(typedef 的类型严格性)
有没有办法对相同类型的 typedef 强制执行显式强制转换? 我必须处理 utf8,有时我会对字符计数和字节计数的索引感到困惑。 因此,最好有一些 typedef:
typedef unsigned int char_idx_t;
typedef unsigned int byte_idx_t;
此外,您需要在它们之间进行显式转换:
char_idx_t a = 0;
byte_idx_t b;
b = a; // compile warning
b = (byte_idx_t) a; // ok
我知道 C 中不存在这样的功能,但也许您知道一个技巧或编译器扩展(最好是 gcc)那。
编辑 总的来说,我仍然不太喜欢匈牙利符号。 由于项目编码约定,我无法使用它来解决这个问题,但我现在在另一个类似的情况下使用它,其中类型也相同,含义也非常相似。 我必须承认:这很有帮助。 我永远不会去声明每个以“i”开头的整数,但正如 Joel 的重叠类型示例中那样,它可以挽救生命。
Is there a way to enforce explicit cast for typedefs of the same type? I've to deal with utf8 and sometimes I get confused with the indices for the character count and the byte count. So it be nice to have some typedefs:
typedef unsigned int char_idx_t;
typedef unsigned int byte_idx_t;
With the addition that you need an explicit cast between them:
char_idx_t a = 0;
byte_idx_t b;
b = a; // compile warning
b = (byte_idx_t) a; // ok
I know that such a feature doesn't exist in C, but maybe you know a trick or a compiler extension (preferable gcc) that does that.
EDIT
I still don't really like the Hungarian notation in general. I couldn't use it for this problem because of project coding conventions, but I used it now in another similar case, where also the types are the same and the meanings are very similar. And I have to admit: it helps. I never would go and declare every integer with a starting "i", but as in Joel's example for overlapping types, it can be life saving.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
对于“句柄”类型(不透明指针),Microsoft 使用声明结构的技巧,然后 typedef'ing 指向该结构的指针:
然后而不是
They do:
所以现在,这是有效的:
For "handle" types (opaque pointers), Microsoft uses the trick of declaring structures and then typedef'ing a pointer to the structure:
Then instead of
They do:
So now, this works:
您可以执行以下操作:
然后您会看到何时使用每个:
现在更清楚它们是不同的类型,但仍然可以编译。
You could do something like:
Then you would see when you are using each:
Now it is more clear that they are different types but would still compile.
你想要的是“强typedef”或“严格typedef”。
一些编程语言 [Rust、D、Haskell、Ada...] 在语言级别对此提供了一些支持,而 C[++] 则没有。 有人提议将其包含到名为“opaque typedef”的语言中,但没有被接受。
不过,缺乏语言支持确实不是问题。 只需将要别名的类型包装到一个新类中,该类恰好有 1 个数据成员(类型为 T)。大部分重复可以通过模板和宏来分解。 这种简单的技术与直接支持的编程语言一样方便。
What you want is called "strong typedef" or "strict typedef".
Some programming languages [Rust, D, Haskell, Ada, ...] give some support for this at language level, C[++] does not. There was a proposal to include it into the language with the name "opaque typedef", but was not accepted.
The lack of language support is really not a problem though. Just wrap the type to be aliased into a new class having exactly 1 data member, of type T. Much of the repetition can be factored out by templates and macros. This simple technique is just as convenient as in the programming languages with direct support.
使用棉绒。 请参阅 Splint:Types 和 强类型检查。
Use a lint. See Splint:Types and strong type check.
在 C 中,由编译器强制执行的唯一用户定义类型之间的区别是结构之间的区别。 任何涉及不同结构的 typedef 都可以工作。 您的主要设计问题是不同的结构类型是否应该使用相同的成员名称?如果是这样,您可以使用宏和其他坏人技巧来模拟一些多态代码。 如果不是,那么你实际上致力于两种不同的表现形式。 例如,您希望能够
在
byte_idx
和char_idx
上使用INCRMENT
吗? 然后以相同的方式命名这些字段。In C, the only distinction between user-defined types that is enforced by the compiler is the distinction between structs. Any typedef involving distinct structs will work. Your major design question is should different struct types use the same member names? If so, you can simulate some polymorphic code using macros and other scurvy tricks. If not, you are really committed to two different representations. E.g., do you want to be able to
and use
INCREMENT
on bothbyte_idx
andchar_idx
? Then name the fields identically.使用 C++11,您可以使用枚举类,例如,
编译器将在两种类型之间强制执行显式强制转换; 它就像一个薄包装类。 不幸的是,您不会有运算符重载,例如,如果您想将两个 char_idx_t 添加在一起,则必须将它们转换为 unsigned int。
With C++11 you can use an enum class, e.g.
The compiler will enforce an explicit cast between the two types; it is like a thin wrapper class. Unfortunately you won't have operator overloading, e.g. if you want to add two char_idx_t together you will have to cast them to unsigned int.
您询问了扩展。 Jeff Foster 的 CQual 非常好,我认为它可以完成您的工作想。
You asked about extensions. Jeff Foster's CQual is very nice, and I think it could do the job you want.
如果您正在编写 C++,则可以创建两个具有不同名称的相同定义的类,它们是 unsigned int 的包装器。 我不知道在 C 中做你想做的事情的技巧。
If you were writing C++, you could make two identically defined classes with different names that were wrappers around an unsigned int. I don't know of a trick to do what you want in C.
使用 BOOST_STRONG_TYPEDEF 中定义的强 typedef
Use strong typedef as defined in BOOST_STRONG_TYPEDEF