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 处的值。

我在 main 中调用这个函数,如下
**

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

**

我使用 gdb 进行了调试,在函数fillin中将值分配给成员,但是一旦控件进入主程序,double 值就会丢失并且不正确。

(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 构建的。非常感谢任何指针或帮助。

4

3 回答 3

1

正如其他人已经提到的那样,这是一个非常糟糕的主意,但是,如果您打包结构以避免填充并使用 achar *并且sizeof()您可能能够摆脱它,例如:

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
于 2013-02-18T12:07:32.560 回答
0

编译器将添加“填充”以对齐结构中的某些类型。填充量取决于编译器、编译的处理器、使用的编译器设置等。

正如“展开”所提到的,提供了一些宏来计算结构的偏移量offsetof(type, member),“做正确的事”。您的代码将浮点数填充到两个 char 变量和实际浮点变量之间的“nomansland”(填充)中,这就是为什么您得到“随机”结果的原因 [显然不是完全随机的 - 只是“不是你所期望的” - 这完全是如果您知道偏移量的差异并找出它提供的浮点值的位模式,则可以预测]。

于 2013-02-18T11:51:31.593 回答
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不是一个好主意

于 2013-02-18T11:51:44.163 回答