【问题标题】:OFFSETOF macro structure fieldOFFSETOF 宏结构域
【发布时间】:2013-11-08 05:20:36
【问题描述】:

使用 OFFSETOF 宏更新结构字段的代码

#include <stdio.h>   
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))   

typedef struct PodTag {    
int     i;    
double  d;    
char    c; 
}PodType;   

#pragma pack(1)
int main() 
{    
     char arr[20] = {'\0'};
     arr[0] = 0x1;
     PodType instance;
     printf("%d\n", OFFSETOF(PodType, c));   
     memset(&instance,0,sizeof(PodType)); 
     memcpy(&instance+OFFSETOF(PodType, c),&arr[0],sizeof(char));
     printf("Val of C = %d\n",instance.c); // value is not reflected
     getchar();    
return 0; 
} 

我在这里做 memcpy 。价值不体现。怎么了

memcpy(&instance+OFFSETOF(PodType, c),&arr[0],sizeof(unsigned char));

我们可以做这样的事情来更新结构字段

#define OFFSETOF_DATA(TYPE, ELEMENT,data) \
  (*((size_t)&(((TYPE *)0)->ELEMENT)) = (unsigned char)(data))  

【问题讨论】:

  • 当标准版本的offseof 可以从标准库的头文件stddef.h 中获得时,为什么要编写自己的OFFSETOF 宏?
  • 你为什么要使用 offsetof 宏,而你只能使用 &amp;instance.c

标签: c macros struct


【解决方案1】:

这行有问题:

 memcpy(&instance+OFFSETOF(PodType, c),&arr[0],sizeof(char));

它将&amp;instance视为数组的开头,并在其上添加一个诸如16之类的数字,从而访问虚构数组第16个成员的i元素。

你需要使用:

 memcpy((char *)&instance+OFFSETOF(PodType, c), &arr[0], sizeof(char));

这会将正确数量的字节添加到&amp;instance 的字节地址。请注意,char * 演员表与 cchar 字段这一事实无关;即使您正在访问 id 元素,您仍然会在那里使用 char * 演员表。

#include <stdio.h>
#include <string.h>

#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))

typedef struct PodTag
{
    int i;
    double d;
    char c;
} PodType;

int main(void)
{
    char arr[20] = {'\0'};
    arr[0] = 0x1;
    PodType instance;
    printf("%zu\n", OFFSETOF(PodType, c));
    memset(&instance, 0, sizeof(PodType));
    memcpy((char *)&instance+OFFSETOF(PodType, c), &arr[0], sizeof(char));
    printf("Val of C = %d\n", instance.c);
    return 0;
}

示例输出(Mac OS X 10.9 Mavericks;GCC 4.8.2,64 位编译):

16
Val of C = 1

【讨论】:

  • 正确答案,但有点不完整。所有这些OFFSETOF 的东西完全没用,OP 应该改用&amp;instance.c
【解决方案2】:

(TYPE*)0

【讨论】:

  • memcpy(&instance+OFFSETOF(PodType, c),&arr[0],sizeof(char)); &instance 将是 struct & 的某个基地址,将返回偏移量..应该可以工作,不是吗
  • 我不同意你的说法,但我认为NULL 正是我的意图。然后,将 NULL 转换为适当的类型,并获取元素的地址,因为它来自 NULL,所以地址将是偏移量。
  • @Macattack:是的,但严格来说,这不是可移植的。空指针的物理表示不必专门指向零地址。即正式的(TYPE *) 0 可以指向0xABCD1234 地址,这将立即破坏该宏的预期功能。这实际上就是为什么人们不得不想知道为什么 OP 决定重新实现标准库中一直很容易获得的东西,作为在stddef.h 中定义的offsetof 宏。
  • 从形式上看,这个宏确实触发了未定义的行为,因为它试图取消引用空指针。
猜你喜欢
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-10
  • 2012-01-29
  • 1970-01-01
  • 2020-06-19
相关资源
最近更新 更多