我正在学习C,我的一些家庭作业遇到了一些麻烦。
我正在尝试使用一个链表,该链表是作为另一个标头中的一个标头的一部分实现的。我的列表实现包括一个typedef
,它看起来像这样:
typedef struct queue_T
{
int count;
struct member_T * first;
struct member_T * last;
} * queue_T;
上述typedef
位于一个源文件(.c
)内。我目前正在尝试编写第二个使用此类型的源文件。在这个源文件中,我试图声明一些queue_T
变量用作全局变量。我是这样做的:
#include <math.h>
#include "mathfns.h"
#include "queue.h"
queue_T primes;
queue_T squares;
queue_T cubes;
primes = new_queue();
squares = new_queue();
cubes= new_queue();
new_queue()
是我的queue_T类型的初始值设定项函数,mathfns.h
是与本段正上方的源文件相关联的头文件。当我尝试编译时,queue_T变量的上述声明默认为整数,当我尝试初始化变量时,它会产生错误。我该如何避免这种情况?我是否应该#include
mathfns.h
文件中的"queue.h
标头"
谢谢。
正如我在评论中所写的,您不能在函数之外执行函数调用。您甚至不能在函数外执行赋值语句,尽管您可以为全局变量提供常量初始化器,并且语法类似于赋值语句。然而,初始化程序是不可执行的——它们由程序执行范围之外的系统处理(您可以将其作为无法在其中执行函数调用的原因)。
假定函数new_queue()
分配一个新的struct queue_T
并对其进行初始化,然后返回一个指向调用者的指针。这很好,也很有用,但如果您只想初始化现有的struct queue_T
结构呢?事实上,如果您想提供这种类型的预初始化全局对象,那么这样的工具正是您所需要的。例如:
static struct queue_T primes_struct = { 0, NULL, NULL };
queue_T const primes = &primes_struct;
/* ... */
但是,编写这样的文字结构初始值设定项既乏味又容易出错。毕竟,如果在编写代码之后结构定义发生了更改,该怎么办?事实上,如果您只是想将struct
的所有成员初始化为零/NULL,那么初始化器的传统形式就是{ 0 }
(单个元素)。但即便如此,经过一些修改,最终也可能不是你想要的。
另一种选择是让queue.h
声明一个宏,该宏可用于初始化一个空的struct queue_T
,并在所有地方使用该宏(包括在函数new_queue()
中,以确保在所有地方执行相同的初始化)。因此,在queue.h
的某个地方,你可能已经。。。
#define EMPTY_QUEUE { 0, NULL, NULL }
在mathfns.c
中,你可以这样做:
static struct queue_T primes_struct = EMPTY_QUEUE;
queue_T const primes = &primes_struct;
这样,如果修改struct queue_T
,就可以对宏进行相应的更改,而不是修改源文件中简单地使用该结构的任何代码。