有没有办法对相同类型的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的重叠类型的例子一样,它可以挽救生命.
你可以这样做:
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;
现在更清楚的是它们是不同类型但仍然可以编译.
对于"句柄"类型(不透明指针),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! */
你想要什么叫做"strong typedef"或"strict typedef".
一些编程语言[Rust,D,Haskell,Ada,...]在语言层面为此提供了一些支持,C [++]没有.有人建议将其包含在名为"opaque typedef"的语言中,但未被接受.
尽管如此,缺乏语言支持确实不是问题.只需将要别名的类型包装到一个新类中,该类具有类型为T的1个数据成员.重复的大部分可以通过模板和宏来计算.这种简单的技术与直接支持的编程语言一样方便.
使用棉绒.请参阅Splint:类型和 强类型检查.
强类型检查通常会显示编程错误.Splint可以比典型的编译器(4.1)更严格和灵活地检查原始C类型,并提供支持布尔类型(4.2).此外,用户可以定义提供信息隐藏的抽象类型(0).
在C中,唯一的用户定义的类型之间的区别是由编译器执行的是区分结构.任何涉及不同结构的typedef都可以工作.您的主要设计问题是不同的结构类型是否应使用相同的成员名称? 如果是这样,你可以使用宏和其他坏血病技巧模拟一些多态代码.如果没有,你真的致力于两种不同的表现形式.例如,你想能够吗?
#define INCREMENT(s, k) ((s).n += (k))
和使用INCREMENT
上都byte_idx
和char_idx
?然后以相同的方式命名字段.