- 论坛徽章:
- 2
|
回复 #23 epegasus 的帖子
原帖由 epegasus 于 2009-8-27 14:47 发表 ![]()
C1无须关心struct S的大小和定义,那它还要struct S*这样的东西,做什么,完全可以剔除,不是吗?如果不同的struct S*只是为了代表不同的实体,那甚至无须struct S出现在C1中了,任何一种标号都能拿来做区分.
思维相当敏锐嘛~~~
确实, 不使用struct S;也是可以的, 比如使用uintptr_t, void*。
struct S; 是利用语言的静态类型检测机制来减少一些错误。
举个uintptr_t的例子:
int fd = open( ... );
++fd; // ??? 语言不阻止你做这个事情
write(fd, ... ); // 不幸
这就是使用uintptr_t 来标识一个对象的不足: 提供过多。
如果只是用于标识一个对象, 算术操作通常是没有意义的, 应尽可能的不提供这个机制。
那么使用void*?
void* 可以避免客户代码对所指对象使用算术操作(ISO C, gcc扩展除外), 以及解引用操作—— 这些操作通常没有意义。
已经是一种不错的方案。 并且相对于uintptr_t, 还有一个可移植性优势:
语言保证任何对象的地址, 都可以保存在void* 对象中, 并且可以原封不动的转换回原来的指针。
int 做不到这点。 而uintptr_t、intptr_t 在c99中是optional的。
相对于void* , 提供一个struct S是有一些好处的。
void* 有另外一些好处, 这里就不说了……
假设:
void* t1_new(void);
void t1_op(void* t1,int);
void t1_delete(void* t1);
void* t2_new(void);
void t2_op(void* t2, double);
void t2_delete(void* t2);
void* o1 = t1_new();
void* o2 = t2_new();
t1_op(o1, 1212 ); // 正确的用法, ok
t1_op(o2, 1212.0); // 错误的用法, 语言无法检测
t2_op(o2, 326.0); // 正确的用法, ok
t2_op(o1, 1212); // 错误的用法, 语言无法检测
t1_delete(o2); // 都是错误的用法
t2_delete(o1); // 语言无法检测
如果换作:
typedef struct t1 t1;
t1* t1_new(void);
void t1_op(t1* o, int);
void t1_delete(t1* o);
typedef struct t2 t2;
t2* t2_new(void);
void t2_op(t2* o, double);
void t2_delete(t2* o);
上面的所有错误用法, 都能在编译时检测出来 |
|