2

Consider the following struct defined in ModuleA:

typedef struct{
    int A;
    int B;
    int C[4];
}myStructType;

myStructType MyStruct;

If I wanted to use this struct from ModuleB, then I would declare the struct in the ModuleA header like this:

extern myStructType MyStruct;

So far, so good. Other modules can read and write MyStruct by including the Module A header file.

Now the question:

How can I declare only part of the struct in the Module A header file? For example, if I wanted ModuleB to be able to read and write MyStruct.C (or, to make things a bit easier, perhaps MyStruct.A or MyStruct.B), but not necessarily know that it's in a struct or know about elements A and B.

Edit: I should probably also specify that this will go in an embedded system which does basically all of its memory allocation at compile time, so we can be extremely confident at compile time that we know where MyStruct is located (and it's not going to move around).

Edit2: I'll also clarify that I'm not necessarily trying to prevent other modules from accessing parts of the struct, but rather, I'm attempting to allow other modules to access individual elements without having to do MyStruct.Whatever because other modules probably only care about a single element and not the whole structure.

4

6 回答 6

3

您必须封装它,即创建一个私有变量,例如:

static myStructType the_struct;

在一些 C 文件中,然后提供一个 API 来访问这些部分:

int * getC(void)
{
  return the_struct.C;
}

这将让其他 C 文件通过调用来访问整数数组

int *some_c = getC();
some_c[0] = 4711;

管他呢。通过更明确地返回数组的长度可以使其“更紧密”,当然,我的目标是最小的解决方案。

于 2012-10-08T14:32:18.547 回答
2

虽然理论上该解决方案的清洁度可能存在一些问题(例如结构对齐),但实际上它通常在编译时工作,如果不编译,您可以更改结构以使其编译:

#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

如果两个结构定义不同步,则会出现编译时错误(matchmismatch)。

PublicStruct您可能需要通过反复试验手动定义 的保留部分的大小。

你明白了。

于 2012-10-08T14:53:38.080 回答
1

您可以尝试使用一种吸气剂:

在模块 A 中:

typedef struct{
    int A;
    int B;
    int C[4];
}myStructType;

myStructType MyStruct;

int getA()
{
    return MyStruct.A;
}

等等。

而是切换到 C++

于 2012-10-08T14:32:19.920 回答
1

长话短说——你不能。为了让它更长一点,你不能可靠地做到这一点。

于 2012-10-08T14:23:43.383 回答
0

您不能完全按照您所描述的那样做,但是通常将结构用作标头,该结构与缓冲区相邻,该缓冲区的内部结构只有特定模块才知道。

这个结构的标题是相当明显的,但它仍然可以作为示例:

typedef struct _FILE_NOTIFY_INFORMATION {
  ULONG NextEntryOffset;
  ULONG Action;
  ULONG NameLength;
  ULONG Name[1];
} FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;

该结构(来自 Microsoft 的 NativeSDK)被设计为可变长度缓冲区的标头。所有模块都可以通过查看 NameLength 来计算缓冲区的长度,但您可以使用此方法将任何内容存储在缓冲区中。这可能只有特定模块才能知道,而其他模块仅使用长度来复制它等等。

于 2012-10-08T14:38:50.543 回答
0

如果它不是为了隐藏而是为了结构化,那么就进行结构化。例如像这样:

模块A.h:

typedef struct{
    int A;
}myStructModuleAType;

extern myStructModuleAType myStructModuleA;

模块A.c:

myStructModuleAType myStructModuleA;

模块B.h:

typedef struct{
    int B;
}myStructModuleBType;

extern myStructModuleBType myStructModuleB;

模块B.c:

myStructModuleBType myStructModuleB;

主.h:

#include "moduleA.h"
#include "moduleB.h"

typedef struct{
    myStructModuleAType * pmyStructModuleA;
    myStructModuleBType * pmyStructModuleB;
    int C[4];
}myStructType;

extern myStructType myStruct;

主.c:

#include "main.h"

myStructType myStruct;

myStructType myStruct = { 
  .pmyStructModuleA = &myStructModuleA
  .pmyStructModuleB = &myStructModuleB
};
于 2012-10-08T15:32:28.807 回答