2013-03-27 66 views
1

用下面的(簡化的)數據定義:管理幾乎相同的數據結構用C

#define DIM0 10 
#define DIM1 15 

typedef struct { 
    uint32_t var1: 
    ... 
    int8_t arrayVar1[DIM0]; 
} dataClass0; 

typedef struct { 
    uint32_t var1: 
    ... 
    int8_t arrayVar1[DIM1]; 
} dataClass1; 

在一個給定的點,我必須創建這些結構的陣列並處理它們。

除了數組(長度不同)之外,處理過程完全相同。現在它是這樣的:

dataClass0 *data; 
data = (dataClass0 *) malloc(dimension * sizeof (dataClass0)); 
// Processing and filling structure 
data[i].var1 = <value> 
... 

現在我有複製給每個數據班組長相同的功能。使用這些數據結構時是否存在重複代碼的方法?

注:

  • 只有純C,沒有C++;
  • 我無法更改數據定義(即不能在結構中使用int8_t *arrayVar1)。
  • 處理時,我收到要處理的數據類型(0表示class0,1表示class1,...)。
+0

這聽起來像是其中一個宏可能是最合適的解決方案之一... – 2013-03-27 12:24:16

+3

您需要着名的** struct hack!** – 2013-03-27 12:24:32

+0

或者一個* flexible數組*,因爲它自C99以來就被稱爲。 – WhozCraig 2013-03-27 12:26:46

回答

3
typedef struct { 
    uint32_t var1: 
    ... 
    int8_t arrayVar[]; /* Declare as flexible array, allowed since C99 */ 
} dataClass; 

有類似的東西分配:

data1 = malloc(sizeof (dataCLass) + DIM1*sizeof ((dataClass*)NULL)->arrayVar[0]); 
data2 = malloc(sizeof (dataCLass) + DIM2*sizeof ((dataClass*)NULL)->arrayVar[0]); 
or define 
#define ALLOCDATA(dim) malloc(sizeof (dataCLass) + (dim)*sizeof ((dataClass*)NULL)->arrayVar[0]); 

定義

#define ELEMENT1(data, i) (dataClass*)(((char*)(data))+(i)*(DIM1+sizeof (dataCLass))) 
#define ELEMENT2(data, i) (dataClass*)(((char*)(data))+(i)*(DIM2+sizeof (dataCLass))) 

,或者如果你參數化的DIM

#define ELEMENT(data, i, dim) (dataClass*)(((char*)(data))+(i)*((dim)+sizeof (dataCLass))) 

享受

ELEMENT1(data1, i)->var1 = 1; 
ELEMENT1(data1, i)->arrayVar1[9] = 4; 


ELEMENT2(data2, i)->arrayVar1[14] = 4; 

ELEMENT(data1, i, DIM1)->var1 = 1; 
ELEMENT(data1, i, DIM1)->arrayVar1[9] = 4; 


ELEMENT(data2, i, DIM2)->arrayVar1[14] = 4; 

並不完美,但不是太怪異構建到無法使用。

編輯: 元素定義應改爲

#define ELEMENT1(data, i) (dataClass*)(((char*)(data))+(i)*(DIM1*sizeof ((dataClass*)NULL)->arrayVar[0]+sizeof (dataCLass))) 
#define ELEMENT2(data, i) (dataClass*)(((char*)(data))+(i)*(DIM2*sizeof ((dataClass*)NULL)->arrayVar[0]+sizeof (dataCLass))) 

#define ELEMENT(data, i, dim) (dataClass*)(((char*)(data))+(i)*((dim)*sizeof ((dataClass*)NULL)->arrayVar[0]+sizeof (dataCLass))) 

這種變化,你arrayVar場可以是任何類型的,並不僅限於大小的元素1.

+1

在C數組中,長度爲'0'是不允許的。你正在接受的是一個擴展。你想做的正式方法是使用'[]'而不是'[0]',它被稱爲靈活數組成員。 – 2013-03-27 12:52:17

+0

好,已編輯。不改變任何東西,但。 – 2013-03-27 12:54:18

+0

確定這個改變,只是正確和不正確的代碼之間的區別。 – 2013-03-27 13:02:37

1

難道你不能只讓陣列動態?所以你用malloc()創建你的結構,然後初始化一些成員來保存大小(並確保它以uint8_t *而不是實際的數組結尾,或使用VLA)?

+0

看來,OP已經解決了這個問題...... – 2013-03-27 12:34:21

+1

顯然不是。 '(即不能在結構中使用int8_t * arrayVar1)。' – Mike 2013-03-27 12:39:09

+0

這是正確的,我不能使用動態數組。 – mcieec 2013-03-27 13:36:33

0

這取決於是否或者不想你最初用不同的值填充數組。否則,你可以有一個初始化兩種類型的結構

#define STRUCTURE_INITIALIZER(VAR1, VAR2) { .var1 = (VAR1), .var2 = (VAR2) } 

的宏觀和使用,作爲

dataClass0 data = STRUCTURE_INITIALIZER(31, 42); 

您的陣列組件隨後將永遠是0初始化,無論大小。

要初始化你的東西的malloc ED陣列:

dataClass0 *data = malloc(dimension * sizeof (dataClass0)); 

// Processing and filling structure 
for (size_t i = 0; i < dimension; ++i) 
    data[i]= (dataClass0)STRUCTURE_INITIALIZER(43, i); 

BTW,寧願正確初始化的變量,不投的malloc回報。