2012-06-21 60 views
0

我有一個C庫存儲記錄與一些領域。模式是從文本文件讀入的,包括記錄中每個字段的類型。C運行時類型檢查

爲了簡化問題的目的,想象我有

typedef enum my_type_enum 
{ 
    INT32, //32-bit integer 
    MYSTRUCT, //some struct I have, details irrelevant 
    ... 
} my_type_enum; 

typedef struct my_var 
{ 
    my_type_enum typetag; 
    unsigned char* data; 
} my_var; 

my_var myrecord[numfields]; 

模式文件說myrecord的每個字段是否應該持有一個int32_t或MYSTRUCT。我的庫讀取模式文件,併爲myrecord中的每個my_var設置標記併爲數據分配適當的空間。

my_var是不透明和客戶端程序基本上使用,對於簡單的數據

void set(my_var* record, size_t field, void * src) 
{ 
    memcpy(record[field].data, src, datatypes[record[field].typetag].size); 
} 

int32_t x = 5; 
set(myrecord, 0, &x); 

存儲在記錄中的值,以及類似的get()取東西出來。

標記的my_var類型允許在數據位於my_var內時進行類型檢查,但是如果模式表示記錄包含三個INT32,那麼當您嘗試訪問數據庫時,當然不需要檢查src是否指向int32_t而不是mystruct。將()數據設置爲my_var。

很明顯,在int32_t *或mystruct *被轉換爲void *之前,檢查需要在包裝set()的東西中進行。我已經看到編譯時檢查typeof()技巧。我覺得我想要的可能是不可能的,但你永遠不知道所有的技巧...

有什麼我可以做得比提供設施,在客戶端程序編譯時讀取模式,並生成一個set_CHECKED )包裝宏,如果有人試圖將int32_t複製到my_var標籤中以保存mystruct,會給出編譯器錯誤? GCC擴展很好。

回答

0

實際上,'set'和'get'似乎是正確的地方放 您的支票。如果訪問字段錯誤類型是一個致命的錯誤 ,修復很簡單:

void set(my_var* record, size_t field, void * src) 
{ 
    if (record[field].typetag != (my_var)src->typetag) { 
     fprintf(stderr, "Type mismatch!\n"); 
     exit(1); 
    } 
    memcpy(record[field].data, src, datatypes[record[field].typetag].size); 
} 

如果一個類型不匹配是不是一個致命的錯誤,你需要做出一套和 獲取返回和錯誤代碼並在呼叫現場正確處理。

請注意,在C中,類型信息在編譯代碼爲 時已消失。 'typetag'字段是您必須知道字段類型的唯一方式。

當然,如果你不需要能夠改變架構而沒有 重新編譯庫,你可以嘗試從它生成C代碼。 這會讓你在編譯時使用編譯器的類型檢查。這個不會改變代碼的正確性,但void *會告訴 閱讀器(和調試器),它不會改變代碼的正確性,類型是未知的。)

+0

我將編輯得更清晰一點,但src參數是指向要存儲的普通數據類型的指針。 'int32_t x = 5;' 'set(myrecord,0,&x);' 不能帶'src-> typetag'。 –