Typedef Struct在C编程中的使用

时间:2018-11-30 22:11:43

标签: c struct typedef

我有一个C模板,可作为作业。但是在做作业之前,我需要清楚地理解“ typedef” “ struct” 的用法,以便继续进行编码。这是代码;

typedef struct NODE_s *NODE;
typedef struct NODE_s
{
    NODE right;
    NODE left;
    unsigned long data;
    int height;
} NODE_t[1];

typedef struct TREE_s *TREE;
typedef struct TREE_s
{
    NODE root;
} TREE_t[1];

TREE tree_init();
NODE node_init(unsigned long data);

首先,typedef struct NODE_s *NODE;行在这里做什么?为什么将其命名为带有*的指针?

然后,在struct定义之后,创建名为NODE_t[1]的变量的目的是将带有数字“ 1” 的方括号与数组相连,或者就是其他东西吗?

最后,当声明tree_init();node_init(unsigned long data);函数时,为什么使用 TREE NODE 数据类型名称却相反在结构定义之前声明为*TREE*NODE?谢谢您的回答。

1 个答案:

答案 0 :(得分:4)

为您提供的模板是这个,为了方便参考,我在其中添加了一些数字:

typedef struct NODE_s *NODE;    // 1
typedef struct NODE_s           // 2
{
    NODE right;                 // 3
    NODE left;
    unsigned long data;
    int height;
} NODE_t[1];                    // 4

typedef struct TREE_s *TREE;
typedef struct TREE_s
{
    NODE root;
} TREE_t[1];

TREE tree_init();               // 5
NODE node_init(unsigned long data);

这里有什么问题?

  1. 如评论中所述,SO Q&A Is it a good idea to typedef pointers建议键入typedef指针不是一个好主意,“函数的指针”(此处不相关)的例外情况有限,也许(但可能不是)不透明的类型。该行有两件事:(1)说“存在带有标签NODE_s的结构类型;(2)名称NODEstruct NODE_s *的同义词。结构类型是目前尚不完整;尚不清楚其成员的详细信息。
  2. 此行开始一个新的typedef,但也开始定义类型struct NODE_s(因为下一行的{)。
  3. 类型NODE是已知的;它可以在这里使用。就像写struct NODE_s *right;一样。
  4. 名称NODE_t是类型struct NODE_s[1]的别名,类型为1 struct NODE_s的数组。目前尚不清楚这将用于什么用途。我对它的存在有保留(至多)。 (您也可以将第1、2、4点中的讨论应用到struct TREE_s类型,并作必要的修正。)
  5. 这是一个函数声明,但不是原型声明。它说tree_init()函数可以用任意数量的任何类型的参数调用,因为没有指定有关这些参数的数量或类型的信息。我们确实知道它不是可变参数函数(可变参数列表,例如printf()),因为那些必须在使用之前必须有完整的原型声明,其范围以, ...)结尾。如果要指定该函数不接受任何参数,请说:TREE tree_init(void);

我认为NODE_tTREE_t类型背后的意图是允许您编写文字,例如:

int main(void)
{
    TREE_t x = { 0 };

    if (x->root != 0)
        return 1;
    return 0;
}

与测试中使用struct NODE_s x和使用x.root相比,我不确定这是否足以保证类型。它确实使您不必在将指针传递给函数时添加&;再次,我不确定是否真的有足够的力量保证它的存在。

我希望看到的模板是:

typedef struct NODE_s NODE;
struct NODE_s
{
    NODE *right;
    NODE *left;
    unsigned long data;
    int height;
};

typedef struct TREE_s TREE;
struct TREE_s
{
    NODE *root;
};

extern TREE *tree_init(void);
extern NODE *node_init(unsigned long data);

这将从typedef语句中删除指针,避免使用有些奇怪的数组类型,并对tree_init()使用显式原型。我个人更喜欢将函数声明标记为extern;在标头中,它们将与标头中声明的那些稀有全局变量上的extern相匹配。许多人宁愿不使用extern,因为编译器仍然会假定这样做–就是这样;最重要的是一致性。

现在将编写main()中的代码:

int main(void)
{
    TREE x = { 0 };

    if (x.root != 0)
        return 1;
    return 0;
}

区别?箭头->变为点.。那里没有很多问题。但是,在调用函数时,您可能会使用&x,而对于TREE_t类型,则只需编写x(因为它是一个数组)。