Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用空心指针和计算的偏移量将值指定给结构的成员_C_Structure_Offset_Void - Fatal编程技术网

C 使用空心指针和计算的偏移量将值指定给结构的成员

C 使用空心指针和计算的偏移量将值指定给结构的成员,c,structure,offset,void,C,Structure,Offset,Void,我试图将值分配给函数中的结构成员,该函数接受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; c

我试图将值分配给函数中的结构成员,该函数接受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中调用此函数,如下所示
**

**

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

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

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

使用警告编译

CVAR = (void *)(pp + 1); 
这将向您提供
警告:算术中使用的“void*”类型的指针

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

假设
sizeof(double)==8
不是一个好主意

正如其他人已经提到的,这是一个非常糟糕的主意,但是,如果您打包结构以避免填充,并使用
char*
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;  
}
#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
这张照片是:

I
S
Z
234.960000
注意:这不适用于不支持未对齐内存访问的体系结构,也可能不支持我不知道的其他问题,因此,一种更方便的方法是让编译器填充结构并使用其他答案建议的
offsetof
宏,其计算结果为成员从结构开头的偏移量,例如:

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;  
}
#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

请不要这样做。您的代码假设了很多不正确的事情,您无法手动计算结构成员偏移量,并且是正确的,因为编译器可以出于对齐目的插入填充。如果必须,请使用
offsetof
。此外,您对右侧的
(void*)
的施法不会产生任何效果。你应该得到编译器的警告,在
void*
上的指针算法不是很好。谢谢你的帮助。谢谢David的及时回答。是的,结果是结构填充问题。多亏了大量的mux,我不知道“attribute_uuuuu((uuu-packed))。当然,如果你使用这种处理器架构时“正确”(或“错误”,取决于你怎么看),它会崩溃-例如Sparc,Mips处理器不喜欢读取未正确对齐的数据,因此无法在这些处理器上运行此代码)。我个人认为这不是一个好的解决方案[当然,它在几乎所有的编译器0中都不起作用-据我所知,只有
gcc
支持这种特殊形式-其他编译器通常有办法实现同样的效果,但很难实现可移植性]@Matstpeterson我完全同意,但是,如果这是唯一一种不使用
offsetof的方式使代码正常工作,那么假设一个允许未对齐内存访问的体系结构,它只会降低速度,我已经添加了一个注释。是的,我的观点是“不允许编译器按照自己的意愿对齐数据”这使得代码非常不可移植,并且很可能比它应该的速度慢。当然,您可以编写自己的“offsetof”变体,但如果已经有了,那就是浪费时间。