不确定我在这里做错了什么。我有一个通过我的程序大量使用的结构。
typedef struct _MyStruct {
// ... handful of non-trivial fields ...
} MyStruct;
我希望(读取,打算)程序的很多部分返回其中一个结构,但是其中许多应该能够返回一个“null”结构,它是一个单例/全局结构。具体的用例是执行功能说“我找不到你要我回来的东西”。
我假设这是一个在头文件中定义变量并在.c文件中初始化它的简单例子。
// MyStruct.h
// ... Snip ...
MyStruct NotFoundStruct;
-
// MyStruct.c
NotFoundStruct.x = 0;
NotFoundStruct.y = 0;
// etc etc
但编译器抱怨初始化不是常量。
由于我不关心这个全局实际在内存中引用的内容,我只关心所有内容都使用相同的全局,我只是尝试删除初始化并简单地将定义留在标题中。
但是当我这样做时:
MyStruct thing = give_me_a_struct(some_input);
if (thing == NotFoundStruct) {
// ... do something special
}
编译器抱怨二进制运算符“==”(或“!=”)的操作数无效。
如何定义诸如全局可重用(始终是相同的内存地址)结构?
答案 0 :(得分:9)
这不能直接回答你的问题,但它不适合评论......
如果你有一个可能需要返回某个函数或者什么都不返回的函数,那么有几个选项比返回“null struct”或“sentinel struct”更好,特别是因为结构在C中不是相等的。
一个选项是返回一个指针,这样你就可以实际返回NULL
来表示你真的没有返回任何东西;这有一个缺点,即具有重要的内存管理含义,即谁拥有指针?你是否必须在堆上创建一个尚未存在的对象才能执行此操作?
更好的选择是将指向结构的指针作为“out”参数,使用该指针存储实际结果,然后返回表示成功或失败的int
状态代码(或{{1如果你有一个C99编译器)。这看起来像是:
bool
如果int give_me_a_struct(MyStruct*);
MyStruct result;
if (give_me_a_struct(&result)) {
// yay! we got a result!
}
else {
// boo! we didn't get a result!
}
返回零,则表示它未找到结果且未填充give_me_a_struct
对象。如果它返回非零值,则表示它确实找到了结果并填充了result
对象。
答案 1 :(得分:2)
C不允许全局非常量赋值。所以你必须在一个函数中执行此操作:
void init() {
NotFoundStruct.x = 0;
NotFoundStruct.y = 0;
}
至于比较,C不知道如何将==
运算符应用于结构。您可以在C ++中重载(重新定义)运算符,但不能在C中重载。
因此,要查看返回值是否为空,您的选项是
bool found = give_me_a_struct(some_input, &thing);
)MyStruct* thing = give_me_a_struct(some_input);
)第三个选项对于其他情况是最通用的,但需要存储更多数据。对于您的具体问题,最好的选择是第一个选项。
答案 2 :(得分:1)
// MyStruct.h
typedef struct _MyStruct {
// fields
} MyStruct;
extern MyStruct NotFoundStruct;
// MyStruct.c
#include "my_struct.h"
MyStruct NotFoundStruct = {0};
但是由于你不能使用==
运算符,你必须找到另一种方法来区分它。一种(不理想的)方式是保留bool
标志以指示有效性。这样,只有必须检查它以确定它是否是有效的实例。
但我认为你应该考虑詹姆斯提出的解决方案
答案 3 :(得分:-1)
在标题中:
// Structure definition then extern MyStruct myStruct;
在包含全局数据的.c中
struct MyStruct myStruct { initialize field 1, initialize field 2, // etc... };