2017-09-14 22 views
-3

我在table.c(他們每個人大約有1500個成員)中定義了幾個相當大的陣列。我需要將它們傳遞給不同的模塊和/或提供一種如何更新它們的方法。在幾個C模塊之間傳遞大陣列

我的問題是如何使它最有效率,而不是浪費記憶。我的想法是做標準getters/setters。因此,如果爲get我將有一個公共職能:

void getTable(tableID, *table) 

tableID會枚舉definying女巫表我想和*table將指針表。我想只有一個引用被傳遞,所以表格不會在內存中「重複」。

然後在otherModule.c我會打電話僅僅指剛

table *myPointer; 
getTable(TableA, myPointerTable). 

它是正確的嗎?

+1

訪問器函數是一個選項,但它們不是必需的。您可以直接引用全局對象。 (例如,'int x [10] = {...};'在一個單元中,'extern int x [10];'在引用'x'的不同單元中)由於數組在指向函數時衰減到指針,不必擔心任何意外的副本,因爲只有指針纔會在函數調用中被複制。 – PSkocik

+1

您能否提供一個如何定義這些數組的示例,以及您打算如何使用它們? –

+0

@PSkocik這導致意大利麪條編程和緊密耦合。非常糟糕的主意。 – Lundin

回答

2

我有幾個非常大的數組定義在table.c中(他們每個人大約有1500名成員)。

在目前的筆記本電腦(有千兆字節的RAM)的數十個數字不是一個大的數組,它是一個微小的數組。今天,大型數組至少有數百萬(機器)號碼,您最好使用C dynamic memory allocation

(當然,如果陣列中的每個元素是一些複雜和繁重的數據結構 - 一些bignum如 - 事情是不同的)

你可以只通過一個指針(到陣列,或至一些structflexible array member結尾)。

順便說一句,當作爲參數傳遞,陣列被衰變成指針(通常爲calling convention使得該地址迅速在一些processor register傳遞)。因此,像

extern double bigarray[123456]; 
foo(bigarray); 

副本數組(但只能通過其地址)。

我的想法是做標準的getters/setters。

這可能是好的,並且可能更具可讀性。

順便說一句,你可以定義這些getters &設置函數作爲一些公共頭文件中的static inline函數(適當地爲#include)。這會讓你的代碼可讀和快速。

+1

誰說OP在做PC編程? – Lundin

+0

我想,如果不是OP會明確*告訴我們(關於嵌入式編程,或關於超級計算機上的HPC)的情況 –

2

數組表達式「衰變」的指針在大多數情況下,因此,如果您定義類似

T humongous[50000]; // for some arbitrary type T 

,並把它傳遞給函數像

foo(humongous); 

什麼foo接收到的是隻用一個指針第一個元素,而不是整個陣列:

void foo(T *arr) { ... } 

注意tha t,在功能參數聲明的情況下,T a[N]T a[]被視爲與T *a相同 - 它們全都將a聲明爲指針T。基本上,你不能將一個數組「按值」傳遞給C中的一個函數。現在,如果你的數組是一個structunion類型的成員,並且你將該類型的表達式傳遞給一個函數,那麼你函數內創建一個整個數組的一個副本:

struct blah { 
    ... 
    T humongous[50000]; 
    ... 
} bletch; 

foo(bletch); 

void foo(struct blah b) { ... } // b is a full copy of bletch 

所以在這種情況下,你可能會想一個一個指針傳遞給bletch代替:

foo(&bletch); 

void foo(struct blah *b) { ... } 
1

二傳手/ getter方法可能是較小的項目一個確定的想法,雖然你可能想要的格式

table_t* getTable (tableID) 

然而,這是不是在OO意義上的純吸功能,因爲你通過公開私人數據一個指針。此外,再入侵可能會成爲這種方法的一個問題。對於需要更長時間維護的大型專業計劃,這是行不通的。

最好的解決方案是將分配留給調用者。

table.h

typedef struct table_t table_t; // forward declaration 

table_t* table_init (size_t size, /* stuff */); 

void table_free (table_t* table); 

table.c:

#include "table.h" 

struct table_t // this will be unknown to the caller 
{ 
    // private, encapsulated data: 
    size_t size; 
    int data[]; // flexible array member 
}; 

table_t* table_init (size_t size, /* stuff */) 
{ 
    table_t* result = malloc(sizeof(*result) + int[size]); 
    if(result == NULL) { /* handle errors */ } 

    result->size = size; 
    do_something(result->data); 

    return result; 
} 

void table_free (table_t* table) 
{ 
    free(table); 
    /* optionally, make the parameter table_t** and set the pointer 
    to NULL after calling free() */ 
} 

caller.c:

#include "table.h" 

table_t* table = table_init(n, /* stuff */); 

table_do_stuff(table); // either setter/getter or actual algorithm 

table_free(table); 

這使您可以間接地通過使用不透明指針做到這一點一個適當的設計,並允許多個實例,這也將重新排序ancy問題。

+0

輕微:'table.h'需要包含'size_t'。也許''? – chux

+1

@chux是的,這是一種僞代碼。標題還需要標頭警衛等。 – Lundin