如何在不丢失“struct”部分的情况下定义一个结构体?

muk1a3rh  于 2023-03-01  发布在  其他
关注(0)|答案(4)|浏览(140)

我想改变一个struct类型的名字(例如timespec),但在这个过程中不丢失"struct"关键字。我认为这是一个很好的方式来向读者传达某个东西是一个struct,所以我希望新的struct名称与普通的struct行为相同(必须在声明和函数参数中写入"struct")
我试过这个:

#include <time.h>

#define TYPE_DEF_STR
#define D

#ifdef TYPE_DEF
    typedef timespec T; 
#elif defined (TYPE_DEF_STR)
    typedef struct timespec T;
#endif

#ifdef A
    struct T my_struct;
#elif defined (B)
    T my_struct;
#endif   

int main() {
#ifdef C
    struct T my_struct;
#elif defined (D)
    T my_struct;
#endif   
    
    my_struct.tv_nsec = 5;
    return 0;
}

// TYPE_DEF     + A = unknown type name ‘timespec’
// TYPE_DEF     + B = unknown type name ‘timespec’
// TYPE_DEF_STR + A = invalid use of undefined type ‘struct T’
// TYPE_DEF_STR + B = WORKS
// TYPE_DEF_STR + C = storage size of ‘my_struct’ isn’t known
// TYPE_DEF_STR + D = WORKS
aoyhnmkz

aoyhnmkz1#

不能为struct标记定义别名。
但这里有一些替代方法,每种方法都有很大的限制:

  • 你可以把struct作为typedef名字的一部分:
typedef struct timespec struct_T;
  • 你可以使用一个预处理器宏:
#define T timespec
cs7cruho

cs7cruho2#

在C语言中,结构、联合和枚举的标记(structunionenum之后的名称)与普通标识符位于不同的名称空间中(包括类型名称),根据C 2018 6.2.3 1. typedef在普通名称空间中声明别名,并且没有在标记名称空间中声明别名的功能,因此,除了用预处理器#define锤击令牌之外,没有办法使一个结构标签引用另一个结构或其标签。
若要使新类型名称指示该类型是结构,请在名称中包括struct,如typedef struct foo struct_T;

u5rb5r59

u5rb5r593#

你可以随意使用它,它们存在于不同的命名空间中,也就是说,struct标签、struct成员有唯一的命名空间,而typedefs在普通命名空间中。
滥用这不是一个好主意。

struct bird  // tag namespace
{
  DWORD bird; // member namespace
};

typedef struct bird bird; // typedef in ordinary namespace

int main (void)
{
  struct bird Bird = { .bird = 1 }; // Bird in ordinary namespace, "struct bird" is tag namespace
  bird BIRD = Bird; // BIRD in ordinary namespace, BIRD and Bird are compatible types
  if(BIRD.bird)
    puts("bird");
}

建议:
typedef struct ....〈-there,它写的是struct。这就是你告诉读者什么东西是struct的方式。经验丰富的程序员总是在使用变量之前先查找它的类型,现在这比以往任何时候都容易,这要归功于IDE的快捷方式。
你可能想研究一下整个Windows的失败,即"Hungerian notation",他们决定将类型作为类型名本身的一部分。这受到了广泛的批评,大约30年后的今天,它仍然被用作如何"不"写C代码的警示性例子。

h6my8fg2

h6my8fg24#

显然,不可能在不丢失结构体部分的情况下定义结构体类型。可以使用预处理器宏来代替。

相关问题