2013-02-18 84 views
2

我想,其接受所述空隙的函數內分配的值,以一個結構的成員*作爲參數,然後填充基於所述偏移計算的數據值結構的成員。使用void指針和偏移計算的分配值,以結構的構件

typedef struct 
    { 
     char C_BFR_LINK[1]; 
     char C_TABLE_DATA[1]; 
     double MF_COD_BALANCE; 
     char C_TYPE_DT[1]; 
    }ANS; 

的作用

void fillin(void *pp) 
{ 

double* FVAR; 
char* CVAR; 
CVAR = pp; 
memcpy(CVAR,"I",1); 
CVAR = (void *)(pp + 1); 
memcpy(CVAR,"S",1); 
FVAR = (void *)(pp + 2); 
*FVAR = 234.96; 
CVAR = (void *) (pp + 10); 
    memcpy(CVAR,"Z",1); 
    return ; 
} 

負責在各自的偏移量1,2中的值,以填補和10

我打電話內主此函數如下
**

int main() 
{ 
    void* p ; 
    ANS ans; 
    fillin(&ans); 
    return 0; 
} 

**

我調試用gdb的功能FILLIN內爲控制涉及到主程序的雙重價值丟失,這不是正確的值被分配給各成員,但一旦。

(gdb) p pp 
$1 = (void *) 0xffffdabc  
(gdb) x /c 0xffffdabc 
0xffffdabc:  73 'I' 
(gdb) x /c 0xffffdabd  
0xffffdabd:  83 'S' 
(gdb) n 
32  *FVAR = 234.96; 
(gdb) n 
33  CVAR = (void *) (pp + 10); 
(gdb) **x /f 0xffffdabe** 
0xffffdabe:  234.96000000000001 
57  return 0; 
(gdb) **p ans** 
$2 = {C_BFR_LINK = "I", C_TABLE_DATA = "S", 
    **MF_COD_BALANCE = 1.9876540305898699e-268**, C_TYPE_DT = "\213"} 

任何人都可以幫我嗎?此代碼正在使用gcc 4.4.6建立任何20120305.指針或幫助是非常讚賞。

+5

請不要這樣做。你的代碼假定了很多事情是不正確的,你不能手動計算結構成員偏移,並且是正確的,因爲編譯器可以插入用於對齊目的的填充。如果必須使用'offsetof'。而且,你在右邊的'(void *)'上不會做任何事情。你應該得到這樣的編譯器警告,'void *'上的指針運算不是很好。 – unwind 2013-02-18 11:44:35

+0

謝謝放鬆幫助我。 – CPPP 2013-02-18 12:25:19

回答

1

至於其他人已經提到這是一個非常糟糕的主意,但是,如果你打包結構,以避免填充和使用char *sizeof()你可能能夠ge牛逼廢除它,例如:

typedef struct { 
    char C_BFR_LINK[1]; 
    char C_TABLE_DATA[1]; 
    double MF_COD_BALANCE; 
    char C_TYPE_DT[1]; 
}__attribute__((__packed__)) ANS; 

void fillin(void *pp) 
{ 
    char* CVAR = pp; 
    double FVAR = 234.96; 
    /* sizeof(char) is always one */ 
    memcpy(CVAR, "I", sizeof(char)); 
    CVAR += sizeof(char); 
    memcpy(CVAR, "S", sizeof(char)); 
    CVAR += sizeof(char); 
    memcpy(CVAR, &FVAR, sizeof(double)); 
    CVAR += sizeof(double); 
    memcpy(CVAR,"Z",1); 
} 
int main() 
{ 
    ANS ans; 
    fillin(&ans); 
    printf("%c\n", ans.C_BFR_LINK[0]); 
    printf("%c\n", ans.C_TABLE_DATA[0]); 
    printf("%c\n", ans.C_TYPE_DT[0]); 
    printf("%f\n", ans.MF_COD_BALANCE); 
    return 0; 
} 

此打印:

I 
S 
Z 
234.960000 

注:這不會對架構這確實支持對齊的內存訪問,以及其他可能的問題,我的工作不知道的,因此,一個更便攜的方式來做到這一點是讓編譯器墊的結構和使用offsetof宏,其他答案的建議,其計算結果爲抵消成員從結構,例如的開頭:

#define offsetof(type, member) __builtin_offsetof (type, member) 
CVAR + offsetof(ANS, C_BFR_LINK); //evaluates to 0 
CVAR + offsetof(ANS, C_TABLE_DATA); //evaluates to 1 
CVAR + offsetof(ANS, MF_COD_BALANCE); //evaluates to 8 
CVAR + offsetof(ANS, C_TYPE_DT); //evaluates to 16 
+1

感謝噸多路複用器,我不知道「__attribute __((__ packed__))」。 – CPPP 2013-02-18 12:26:49

+0

當然,如果您在使用此處理器時遇到「正確」(或「錯誤」,取決於您如何看待它)處理器架構,它會崩潰 - 例如, Sparc,Mips處理器不會喜歡讀取未正確對齊的數據 - 因此您無法在這些處理器上運行此代碼)。我個人認爲這不是一個很好的解決方案[當然,這並不靠近所有的編譯器0-工作在任何地方,據我所知,只有'gcc'支持這種特殊形式 - 其他編譯器通常有實現的一種方式相同,但它很難便攜] – 2013-02-18 12:32:34

+0

@MatsPetersson我完全同意,但AFAIK這是讓代碼工作而不使用'offsetof'的唯一方法,假設一個架構允許不對齊的內存訪問,它只會減慢速度不管怎樣,我已經添加了一個音符。 – iabdalkader 2013-02-18 12:37:00

0

編譯器將添加「填充」在你的結構對齊某些類型。填充量依賴於編譯器,編譯什麼處理器,使用什麼編譯器設置,等等,等等

如由「放鬆」,有提供以計算偏移量的結構,offsetof(type, member)宏提到的,哪個「做正確的事」。您的代碼充塞一個浮動到您的兩個char變量和實際浮點變量之間的「nomansland」(填充),這就是爲什麼你所得到的「隨機」結果[顯然不是完全隨機的 - 只是「不是你所期望的」 - 這是完全可預見的,如果你知道在偏移的差異,找出浮點值,這個規定]的位模式。

+0

Thankyou,Mats Peterson – CPPP 2013-02-18 12:25:54

0

編譯警告

CVAR = (void *)(pp + 1); 

這給你warning: pointer of type ‘void *’ used in arithmetic

FVAR = (void *)(pp + 2); 
*FVAR = 234.96; 
CVAR = (void *) (pp + 10); 

假設sizeof(double) == 8是不是一個好主意

+0

感謝David提供的答案。是的,結果是結構填充問題。 – CPPP 2013-02-18 12:24:52