qui*_*ars 35 c typedef typechecking strong-typing
有没有办法对相同类型的typedef强制执行显式转换?我要处理utf8,有时我会对字符数和字节数的索引感到困惑.所以有一些typedef很好:
typedef unsigned int char_idx_t;
typedef unsigned int byte_idx_t;
Run Code Online (Sandbox Code Playgroud)
除此之外,您需要在它们之间进行显式转换:
char_idx_t a = 0;
byte_idx_t b;
b = a; // compile warning
b = (byte_idx_t) a; // ok
Run Code Online (Sandbox Code Playgroud)
我知道C中不存在这样的功能,但也许你知道一个技巧或编译器扩展(更好的gcc).
编辑 我仍然不喜欢一般的匈牙利符号.由于项目编码惯例,我无法将它用于此问题,但我现在在另一个类似的情况下使用它,其中类型相同且含义非常相似.我不得不承认:它有所帮助.我永远不会用起始"i"来声明每个整数,但是就像Joel的重叠类型的例子一样,它可以挽救生命.
lil*_*llq 19
你可以这样做:
typedef struct {
unsigned int c_idx;
} char_idx;
typedef struct {
unsigned int b_idx;
} byte_idx;
Run Code Online (Sandbox Code Playgroud)
然后你会看到你在使用每个时:
char_idx a;
byte_idx b;
b.b_idx = a.c_idx;
Run Code Online (Sandbox Code Playgroud)
现在更清楚的是它们是不同类型但仍然可以编译.
Tim*_*her 19
对于"句柄"类型(不透明指针),Microsoft使用声明结构的技巧,然后键入def指向结构的指针:
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; \
typedef struct name##__ *name
Run Code Online (Sandbox Code Playgroud)
然后而不是
typedef void* FOOHANDLE;
typedef void* BARHANDLE;
Run Code Online (Sandbox Code Playgroud)
他们是这样:
DECLARE_HANDLE(FOOHANDLE);
DECLARE_HANDLE(BARHANDLE);
Run Code Online (Sandbox Code Playgroud)
所以现在,这有效:
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! */
Run Code Online (Sandbox Code Playgroud)
lib*_*ako 14
你想要什么叫做"strong typedef"或"strict typedef".
一些编程语言[Rust,D,Haskell,Ada,...]在语言层面为此提供了一些支持,C [++]没有.有人建议将其包含在名为"opaque typedef"的语言中,但未被接受.
尽管如此,缺乏语言支持确实不是问题.只需将要别名的类型包装到一个新类中,该类具有类型为T的1个数据成员.重复的大部分可以通过模板和宏来计算.这种简单的技术与直接支持的编程语言一样方便.
在C中,唯一的用户定义的类型之间的区别是由编译器执行的是区分结构.任何涉及不同结构的typedef都可以工作.您的主要设计问题是不同的结构类型是否应使用相同的成员名称? 如果是这样,你可以使用宏和其他坏血病技巧模拟一些多态代码.如果没有,你真的致力于两种不同的表现形式.例如,你想能够吗?
#define INCREMENT(s, k) ((s).n += (k))
Run Code Online (Sandbox Code Playgroud)
和使用INCREMENT上都byte_idx和char_idx?然后以相同的方式命名字段.
如果您正在编写 C++,则可以创建两个具有不同名称的相同定义的类,它们是 unsigned int 的包装器。我不知道在 C 中做你想做的事情的技巧。