1

我想使用指针算法从数据包结构中获取一些字段。但是下面的代码有什么问题?
在第一种情况下,我认为如果我从数据包的开头开始 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;
}
4

6 回答 6

3

使用标准方法肯定会更好

int *timeLow = &(pck->tLow);

允许编译器在结构的任何成员之间插入填充字节。这些填充字节的规则充其量是实现定义的......因此您必须查阅您的实现手册以确定在您的特定情况下如何(或是否)以及插入多少字节。另请注意,填充字节的数量可能会随着不同选项的编译或编译器之间的不同而不同(计算机到计算机,...)

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

size_t offset = offsetof(struct packet, tLow);
/* make sure offset is a multiple of sizeof (int*) */
int *timeLow = (int*)pck + offset / sizeof (int*);

或者,使用强制转换(char*) 并从其他答案中复制代码变得不那么难看:-)

size_t offset = offsetof(struct packet, tLow);
int *timeLow = (int*)((char*)pck + offset);

哦!并且您的源代码中缺少分号

于 2010-10-07T14:01:22.513 回答
2

您正在寻找offsetof

您的代码可能如下所示:

int *timeLow = (int*) ((char*)pck + offsetof(struct packet, tLow);

正如pmg所指出的,

int *timeLow = &(pck->tLow);

是获取指向结构成员的指针的规范方法。

这个答案也带来了指针算术——感谢pmg,我今天学到了。

于 2010-10-07T13:56:59.640 回答
2

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

(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。

我们基本上是在获取一个指向 void* 的指针。所以代码将如下所示:

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

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

于 2010-10-07T13:57:37.233 回答
1

当你写

int *timeLow = (int * )pck + 4

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

相反,您需要这样做

int *timeLow = (int*)((short * )pck + 2); 
于 2010-10-07T13:50:17.347 回答
0

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

于 2010-10-07T13:51:00.647 回答
0

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

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

于 2010-10-07T13:51:41.290 回答