如何在不复制代码的情况下创建不可转换的C类型?

如何在不复制代码的情况下创建不可转换的C类型?,c,types,type-conversion,typedef,type-safety,C,Types,Type Conversion,Typedef,Type Safety,我有一些C代码,其中包含各种函数,每个函数都以不同类型的“句柄”对象作为参数。所有这些句柄的实现都是相同的(它只是一个带有空指针和项计数的结构),因此只声明一个实现似乎是合乎逻辑的——但我还希望C编译器在用户将错误类型的句柄传递给函数时生成编译时错误 我目前的方法是使用typedef创建各种句柄类型,用于记录函数应接受的句柄类型,但编译器会自动转换,因此不会将类型不匹配标记为错误。有没有一种推荐的方法来实现这一点,即不需要为每种类型手动复制句柄结构声明 玩具示例代码如下: typedef str

我有一些C代码,其中包含各种函数,每个函数都以不同类型的“句柄”对象作为参数。所有这些句柄的实现都是相同的(它只是一个带有空指针和项计数的结构),因此只声明一个实现似乎是合乎逻辑的——但我还希望C编译器在用户将错误类型的句柄传递给函数时生成编译时错误

我目前的方法是使用
typedef
创建各种句柄类型,用于记录函数应接受的句柄类型,但编译器会自动转换,因此不会将类型不匹配标记为错误。有没有一种推荐的方法来实现这一点,即不需要为每种类型手动复制句柄结构声明

玩具示例代码如下:

typedef struct _FruitHandle {
   int _numItems;
   void * _items;
} FruitHandle;

typedef FruitHandle AppleHandle;
typedef FruitHandle BananaHandle;
// imagine a number of other fruits as well

void EatAnApple(AppleHandle a) {}
void EatABanana(BananaHandle b) {}
// and so on -- each function should ONLY except its own fruit-handle-type as an argument!

int main(int argc, char ** argv)
{
   AppleHandle apple;
   BananaHandle banana;

   EatAnApple(apple);  // ok -- types match
   EatABanana(banana); // ok -- types match

   EatAnApple(banana); // type mismatch -- I want this to be a compile-time error, but it isn't!
   EatABanana(apple);  // type mismatch -- I want this to be a compile-time error, but it isn't!

   return 0;
}

如注释中所述,可以使用宏执行此操作:

#define FRUIT(name) typedef struct _##name {\
   int _numItems;\
   void * _items;\
} name

FRUIT(AppleHandle);
FRUIT(BananaHandle);
这扩展到:

typedef struct _AppleHandle { int _numItems; void * _items;} AppleHandle;
typedef struct _BananaHandle { int _numItems; void * _items;} BananaHandle;

如注释中所述,可以使用宏执行此操作:

#define FRUIT(name) typedef struct _##name {\
   int _numItems;\
   void * _items;\
} name

FRUIT(AppleHandle);
FRUIT(BananaHandle);
这扩展到:

typedef struct _AppleHandle { int _numItems; void * _items;} AppleHandle;
typedef struct _BananaHandle { int _numItems; void * _items;} BananaHandle;

你可能会发现这个问题的答案很有帮助。虽然C中没有显式的类型继承,但是您可以使用上面答案中描述的习惯用法来创建AppleHandle和BananaHandle

typedef struct {
    int _numItems;
    void *_items;
} FruitHandle;

typedef struct {
    FruitHandle fruit_handle;
} AppleHandle;

typedef struct {
    FruitHandle fruit_handle;
} BananaHandle;

...

你可能会发现这个问题的答案很有帮助。虽然C中没有显式的类型继承,但是您可以使用上面答案中描述的习惯用法来创建AppleHandle和BananaHandle

typedef struct {
    int _numItems;
    void *_items;
} FruitHandle;

typedef struct {
    FruitHandle fruit_handle;
} AppleHandle;

typedef struct {
    FruitHandle fruit_handle;
} BananaHandle;

...

您可以编写一个宏来定义这些结构。我认为没有比这更好的了,真的
typedef
是一个别名,您需要的是互不兼容的类型。缺点似乎是当您带来程序不知道的结果时。已知的结果是硬编码的,但软结果是不可接受的。我宁愿创建具有
水果句柄
字段的结构。因此,您可以使用其独特的属性扩展每个
果实
。而且,如果您的结构确实是12字节的,那么编译器进行类型检查的好处远远超过节省24字节的存储空间。您可以编写一个宏来定义这些结构。我认为没有比这更好的了,真的
typedef
是一个别名,您需要的是互不兼容的类型。缺点似乎是当您带来程序不知道的结果时。已知的结果是硬编码的,但软结果是不可接受的。我宁愿创建具有
水果句柄
字段的结构。因此,您可以使用其独特的属性扩展每个
水果
。而且,如果您的结构确实是12字节的,那么编译器进行类型检查的好处远远超过节省24字节的存储空间。以下划线开头并后跟大写字母的标识符保留供任何使用。我只想让struct标记与类型名相同。它们在不同的名称空间中。以下划线开头,后跟大写字母的标识符保留供任何使用。我只想让struct标记与类型名相同。无论如何,它们在不同的名称空间中。