2012-10-08 105 views
2

考慮定義的變量下面的結構在ModuleA定義聲明其在結構

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

myStructType MyStruct; 

如果我想用從ModuleB這個結構,那麼我會聲明在ModuleA的結構頭像是這樣的:

extern myStructType MyStruct; 

到目前爲止,這麼好。其他模塊可以通過包含Module A頭文件來讀寫MyStruct。

現在的問題是:

我怎樣才能聲明只能在模塊頭文件的結構的一部分?例如,如果我希望ModuleB能夠讀取和寫入MyStruct.C(或者爲了使事情變得更簡單,可能是MyStruct.A或MyStruct.B),但不一定知道它在結構中或知道元素A和B.

編輯:我也許應該指定這將在嵌入式系統中執行,它基本上在編譯時進行所有的內存分配,所以我們可以在編譯時非常自信地知道MyStruct在哪裏位於(並且它不會移動)。

EDIT2:我還要澄清一點,我並不想防止其他模塊訪問該結構的部分,而是,我試圖允許其他模塊訪問單個元素,而無需去做MyStruct.Whatever,因爲其他模塊可能只關心單個元素而不關注整個結構。

回答

3

你將不得不將其封裝,即做一個私有變量如:

static myStructType the_struct; 
在一些C文件

,然後提供一個API來獲取訪問部分:

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

這會讓其他C文件通過調用

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

或其他任何東西來獲得訪問整數數組的權限。它可以通過更清楚地瞭解返回數組的長度而變得更「緊密」,我的目標是達到最小的解決方案。

1

爲了使長話短 - 你不能。爲了使它更長一點,你不能可靠地做到這一點。

+1

肯定有辦法做到這一點,如果我們包括醜陋的黑客是可能的答案。例如:#define StructElementA((&MyStruct.A)*)no? –

+0

是的,爲了讓故事更長,例如,可以用填充符而不是「不可訪問」元素聲明結構。但是這不會是可靠的。不過,不知道你的'#define'如何解決這個問題。 –

1

你可以嘗試用一種吸氣劑:

在ModuleA

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

myStructType MyStruct; 

int getA() 
{ 
    return MyStruct.A; 
} 

等。

而是切換到C++

0

你不能做的正是你所描述什麼,但它是常見的有作爲標題,這是連續與它有它的內部只知道一個緩衝區一個struct特定模塊。

這是相當清楚該結構是頭,但它仍然可以作爲一個例子:

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

這個結構(從微軟NativeSDK)被設計爲一個可變長度的緩衝器的頭部。所有模塊都可以通過查看NameLength來計算緩衝區的時間長度,但您可以使用此方法將任何內容存儲在緩衝區中。這可能只被一個特定的模塊知道,其他人只是使用長度來複制它等。

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 

如果兩個結構定義超出s ync,你會得到一個編譯時錯誤(match,mismatch)。

您需要手動定義PublicStruct的保留部分的大小,也許需要反覆試驗。

你明白了。

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 
};