考虑ModuleA中的以下结构已定义:
typedef struct{
int A;
int B;
int C[4];
}myStructType;
myStructType MyStruct;
如果我想使用ModuleB中的这个结构,那么我将声明 ModuleA标题中的结构,如下所示:
extern myStructType MyStruct;
到目前为止,这么好。其他模块可以通过包含Module A头文件来读写MyStruct。
现在的问题是:
如何声明仅模块A头文件中的部分结构?例如,如果我希望ModuleB能够读取和编写MyStruct.C(或者,为了使事情变得更容易,可能是MyStruct.A或MyStruct.B),但不一定知道它在结构中或者知道元素A和B.
编辑:我可能还应该指定这将在嵌入式系统中进行,它在编译时基本上完成所有内存分配,因此我们可以非常自信地在编译时知道MyStruct所在的位置(并且它不是要四处走动。)
Edit2:我还要澄清一点,我不一定试图阻止其他模块访问结构的某些部分,而是我试图允许其他模块可以访问单个元素而无需执行MyStruct.Whatever,因为其他模块可能只关心单个元素而不是整个结构。
答案 0 :(得分:3)
你必须封装它,即创建一个私有变量,如:
static myStructType the_struct;
在某个C文件中,然后提供API以访问这些部分:
int * getC(void)
{
return the_struct.C;
}
然后,通过调用,这将允许其他C文件访问整数数组
int *some_c = getC();
some_c[0] = 4711;
或其他什么。当然,通过更明确地返回数组的长度可以使它更“严格”,我的目标是最小化解决方案。
答案 1 :(得分:2)
虽然理论上这个解决方案的清洁度可能存在一些问题(例如结构对齐),但实际上它通常在编译时有效,如果不编译,你可以改变结构以使其编译: / p>
#include <stddef.h>
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
// You keep this definition private to module A (e.g. in a .c file):
typedef struct
{
int A;
int B;
int C[4];
} PrivateStruct;
// You expose this definition to all modules (in an .h file):
typedef struct
{
char reserved[2*sizeof(int)];
int C[4];
} PublicStruct;
// You put these in module A (in a .c file):
C_ASSERT(sizeof(PrivateStruct) == sizeof(PublicStruct));
C_ASSERT(offsetof(PrivateStruct,C) == offsetof(PublicStruct,C));
int main(void)
{
return 0;
}
在公共.h文件中,您可以向全世界介绍全局变量类型:
extern PublicStruct MyStruct; // It's "PrivateStruct MyStruct;" in module A
如果两个结构定义不同步,则会出现编译时错误(match,mismatch)。
您可能需要手动定义PublicStruct
的保留部分的大小,可能是通过反复试验。
你明白了。
答案 2 :(得分:1)
长话短说 - 你做不到。为了使它更长一些,你无法可靠地做到这一点。
答案 3 :(得分:1)
您可以尝试使用一种吸气剂:
在ModuleA中:
typedef struct{
int A;
int B;
int C[4];
}myStructType;
myStructType MyStruct;
int getA()
{
return MyStruct.A;
}
等等。
而是切换到c ++
答案 4 :(得分:0)
你不能完全按照你所描述的那样做,但是将结构用作标题是很常见的,它与缓冲区是连续的,只有特定模块知道它的内部结构。
这个结构是什么标题很明显,但它仍然作为一个例子:
typedef struct _FILE_NOTIFY_INFORMATION {
ULONG NextEntryOffset;
ULONG Action;
ULONG NameLength;
ULONG Name[1];
} FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;
此结构(来自Microsofts NativeSDK)被设计为可变长度缓冲区的标头。所有模块都可以通过查看NameLength来计算缓冲区的长度,但是您可以使用此方法将任何内容存储在缓冲区中。这可能只是由特定模块知道,而其他模块只是使用长度来复制它等等。
答案 5 :(得分:0)
如果不是为了隐藏而是为了构造,那么就构建它。例如:
moduleA.h:
typedef struct{
int A;
}myStructModuleAType;
extern myStructModuleAType myStructModuleA;
moduleA.c:
myStructModuleAType myStructModuleA;
moduleB.h:
typedef struct{
int B;
}myStructModuleBType;
extern myStructModuleBType myStructModuleB;
moduleB.c:
myStructModuleBType myStructModuleB;
main.h:
#include "moduleA.h"
#include "moduleB.h"
typedef struct{
myStructModuleAType * pmyStructModuleA;
myStructModuleBType * pmyStructModuleB;
int C[4];
}myStructType;
extern myStructType myStruct;
main.c中:
#include "main.h"
myStructType myStruct;
myStructType myStruct = {
.pmyStructModuleA = &myStructModuleA
.pmyStructModuleB = &myStructModuleB
};