有没有办法对同一类型的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的重叠类型示例一样,它可以挽救生命。
答案 0 :(得分:19)
您可以执行以下操作:
typedef struct {
unsigned int c_idx;
} char_idx;
typedef struct {
unsigned int b_idx;
} byte_idx;
然后你会看到你在使用每个时间:
char_idx a;
byte_idx b;
b.b_idx = a.c_idx;
现在更清楚的是它们是不同的类型,但仍然可以编译。
答案 1 :(得分:18)
对于“handle”类型(不透明指针),Microsoft使用声明结构的技巧,然后键入def指向结构的指针:
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; \
typedef struct name##__ *name
然后代替
typedef void* FOOHANDLE;
typedef void* BARHANDLE;
他们这样做:
DECLARE_HANDLE(FOOHANDLE);
DECLARE_HANDLE(BARHANDLE);
现在,这有效:
FOOHANDLE make_foo();
BARHANDLE make_bar();
void do_bar(BARHANDLE);
FOOHANDLE foo = make_foo(); /* ok */
BARHANDLE bar = foo; /* won't work! */
do_bar(foo); /* won't work! */
答案 2 :(得分:14)
您想要的是“strong typedef”或“strict typedef”。
一些编程语言[Rust,D,Haskell,Ada,...]在语言层面为此提供了一些支持,C [++]没有。有人建议将其包含在名为“opaque typedef”的语言中,但未被接受。
缺乏语言支持确实不是问题。只需将要别名的类型包装到一个新类中,该类具有类型为T的1个数据成员。重复的大部分可以通过模板和宏来计算。这种简单的技术与直接支持的编程语言一样方便。
答案 3 :(得分:7)
使用棉绒。请参阅Splint:Types和strong type check。
强类型检查经常显示 编程错误。夹板可以检查 原始C类型更严格和 灵活地比典型的编译器(4.1) 并提供支持布尔类型 (4.2)。此外,用户可以定义 提供的抽象类型 信息隐藏(0)。
答案 4 :(得分:5)
在C中,编译器强制执行用户定义类型之间的唯一区别是结构之间的区别。任何涉及不同结构的typedef都可以工作。您的主要设计问题是不同的结构类型是否使用相同的成员名称?如果是这样,您可以使用宏和其他坏血病技巧模拟一些多态代码。如果没有,你真的致力于两种不同的表现形式。例如,您希望能够
吗?#define INCREMENT(s, k) ((s).n += (k))
并在INCREMENT
和byte_idx
上使用char_idx
?然后以相同的方式命名字段。
答案 5 :(得分:3)
您询问了有关扩展的信息。杰夫福斯特的CQual非常好,我认为它可以完成你想要的工作。
答案 6 :(得分:2)
如果你正在编写C ++,你可以创建两个具有不同名称的相同定义的类,这些类是unsigned int的包装器。我不知道在C中做你想做的事情的技巧。
答案 7 :(得分:2)
答案 8 :(得分:1)
使用C ++ 11,您可以使用枚举类,例如
enum class char_idx_t : unsigned int {};
enum class byte_idx_t : unsigned int {};
编译器将在两种类型之间强制执行显式转换;它就像一个薄的包装类。不幸的是,你不会有运算符重载,例如如果要将两个char_idx_t一起添加,则必须将它们转换为unsigned int。