C void*赋值问题

C void*赋值问题,c,pointers,void-pointers,pointer-arithmetic,C,Pointers,Void Pointers,Pointer Arithmetic,我想使用指针算法从数据包结构中提取一些字段。但是下面的代码有什么问题吗? 在第一种情况下,我认为若我从数据包的开头开始走4字节(2个短字段),我得到的是tLow。但它并没有给出预期的值。另外,第二种情况下,我想从数据包的开头走12字节,得到数据字段。我的想法有什么不对 struct packet{ short len; short field; int tLow; int tHigh; void *data; } int main

我想使用指针算法从数据包结构中提取一些字段。但是下面的代码有什么问题吗?
在第一种情况下,我认为若我从数据包的开头开始走4字节(2个短字段),我得到的是tLow。但它并没有给出预期的值。另外,第二种情况下,我想从数据包的开头走12字节,得到数据字段。我的想法有什么不对

struct packet{  
      short len;
      short field;
      int tLow;
      int tHigh;
      void *data;
}

int main()
{
    struct packet pack;
    struct packet *pck;

    pack.len=3;
    pack.field=34;
    pack.tLow=712;
    pack.tHigh = 12903;
    pack.data = "message";

    pck = &pack;
    int *timeLow = (int * )pck + 4; // i want to get tLow 
    printf("Time Low :%d\n",*time);

    char *msg = (char *)pck + 12 ;// want data 
    printf("Message :%s\n",msg);

    return 0;
}
当你写作时

int *timeLow = (int * )pck + 4
您将“pck”视为int指针,取决于您的系统,它可能是4或8个字节。 这将不会正确地偏移到结构中,因为您会告诉它偏移量为4 int

相反,你需要这样做

int *timeLow = (int*)((short * )pck + 2); 
当你写作时

int *timeLow = (int * )pck + 4
您将“pck”视为int指针,取决于您的系统,它可能是4或8个字节。 这将不会正确地偏移到结构中,因为您会告诉它偏移量为4 int

相反,你需要这样做

int *timeLow = (int*)((short * )pck + 2); 

短裤不一定是2字节长。所指定的只是它们小于或等于整数的大小。您可能应该使用sizeof()

Shorts不一定是2字节长。所指定的只是它们小于或等于整数的大小。您可能应该使用sizeof()

这是错误的:
pack.data=“message”
您正在使用未分配的内存

还有:
int*timeLow=(int*)pck+4

不能保证工作(结构对齐方式因编译器和系统而异)。

这是错误的:
pack.data=“message”
您正在使用未分配的内存

还有:
int*timeLow=(int*)pck+4
不保证工作(编译器和系统之间的结构对齐方式各不相同)。

您正在寻找的

您的代码可能如下所示:

int *timeLow = (int*) ((char*)pck + offsetof(struct packet, tLow);
char **msg = (char**)((char *)pck + 16) ;// want data 
printf("Message :%s\n",*msg);
正如pmg所指出的

int *timeLow = &(pck->tLow);
是获取指向结构成员的指针的规范方法

这个答案也被提上了台面——多亏了pmg,我今天才学到了这一点。

您正在寻找的答案

您的代码可能如下所示:

int *timeLow = (int*) ((char*)pck + offsetof(struct packet, tLow);
char **msg = (char**)((char *)pck + 16) ;// want data 
printf("Message :%s\n",*msg);
正如pmg所指出的

int *timeLow = &(pck->tLow);
是获取指向结构成员的指针的规范方法


这个答案也摆在了桌面上——多亏了pmg,我今天才学到了这一点。

基本上,你依赖的是未定义的行为。结构对齐等,但无论如何

(int*)pck+4。将指针前进4*sizeof(int)。这是错误的,如果我们假设结构是压缩的,并且sizeof(short)==2,那么我们希望将其提升1,因此

int *timeLow = (int * )pck + 1; // i want to get tLow 
printf("Time Low :%d\n",*timeLow);
打印正确的结果

至于信息,你需要做一些肮脏的事情。因为我在x86_64上,编译器选择在8字节边界上填充void*,所以偏移量是16,而不是预期的12

我们基本上是获取一个指向一个空*的指针。因此,代码将如下所示:

int *timeLow = (int*) ((char*)pck + offsetof(struct packet, tLow);
char **msg = (char**)((char *)pck + 16) ;// want data 
printf("Message :%s\n",*msg);

永远不要编写这样的代码,这只是说明了一点。

基本上您依赖于未定义的行为。结构对齐等,但无论如何

(int*)pck+4。将指针前进4*sizeof(int)。这是错误的,如果我们假设结构是压缩的,并且sizeof(short)==2,那么我们希望将其提升1,因此

int *timeLow = (int * )pck + 1; // i want to get tLow 
printf("Time Low :%d\n",*timeLow);
打印正确的结果

至于信息,你需要做一些肮脏的事情。因为我在x86_64上,编译器选择在8字节边界上填充void*,所以偏移量是16,而不是预期的12

我们基本上是获取一个指向一个空*的指针。因此,代码将如下所示:

int *timeLow = (int*) ((char*)pck + offsetof(struct packet, tLow);
char **msg = (char**)((char *)pck + 16) ;// want data 
printf("Message :%s\n",*msg);

永远不要编写这样的代码,这只是说明了一点。

使用标准方法肯定会更好

int *timeLow = &(pck->tLow);
允许编译器在结构的任何成员之间插入填充字节。这些填充字节的规则最多是由实现定义的。。。因此,您必须查阅您的实现手册,以确定如何(或是否)以及在特定情况下插入多少字节。还请注意,填充字节的数量可能会随着不同选项的编译或编译器(计算机到计算机,…)的不同而变化

您可以尝试使用
C
offsetof
,但它并不漂亮:

size_t offset = offsetof(struct packet, tLow);
/* make sure offset is a multiple of sizeof (int*) */
int *timeLow = (int*)pck + offset / sizeof (int*);
或者,使用cast to
(char*)
并从其他答案复制代码,就不那么难看了:-)


哦!!而且你的资料中缺少一个分号

使用标准方法肯定会更好

int *timeLow = &(pck->tLow);
允许编译器在结构的任何成员之间插入填充字节。这些填充字节的规则最多是由实现定义的。。。因此,您必须查阅您的实现手册,以确定如何(或是否)以及在特定情况下插入多少字节。还请注意,填充字节的数量可能会随着不同选项的编译或编译器(计算机到计算机,…)的不同而变化

您可以尝试使用
C
offsetof
,但它并不漂亮:

size_t offset = offsetof(struct packet, tLow);
/* make sure offset is a multiple of sizeof (int*) */
int *timeLow = (int*)pck + offset / sizeof (int*);
或者,使用cast to
(char*)
并从其他答案复制代码,就不那么难看了:-)


哦!!您的源代码中缺少一个分号

或(int*)((无符号字符*)pck+4)谢谢,我意识到我的错误,将pck视为整数。首先转换为字符,然后进行字节计算是我认为安全的方法。或(int*)((无符号字符*)pck+4)谢谢,我意识到我的错误是把pck当作整数处理。首先转换成字符,然后进行字节计算,我认为是安全的方法。+1表示从不。永不言败。。。除必要时外:-)@pmg:adding
k
(char*)
将地址移动
k*sizeof(char)
,即元素类型,
sizeof(char)
根据定义给出1。+1表示从不。永不言败。。。除非必要:-)@pmg:adding
k
(char*)
将地址移动
k*sizeof(char)
,即元素类型,
sizeof(char)
定义为1。@pmg,真的吗?我不明白怎么会这样,你是说@pmg:the
(