如果数组大小发生变化以及定义的宏如何在此处计算偏移量,为啥 C 结构中的字符数组的偏移量会有所不同? [复制]

Posted

技术标签:

【中文标题】如果数组大小发生变化以及定义的宏如何在此处计算偏移量,为啥 C 结构中的字符数组的偏移量会有所不同? [复制]【英文标题】:Why Offset varies for character array in C structure if array size changes and how the defined macro is calculating offset here? [duplicate]如果数组大小发生变化以及定义的宏如何在此处计算偏移量,为什么 C 结构中的字符数组的偏移量会有所不同? [复制] 【发布时间】:2021-05-21 18:03:32 【问题描述】:

我已经定义了一个宏来计算结构到任何结构字段的偏移量。 代码如下:

#define offset(struct_name, fld_name) \
(unsigned int)&(((struct_name *)0)->fld_name)

typedef struct emp_
   char name[20];
   unsigned int salary;
   char designation[30];
   unsigned int emp_id;
 emp_t;

int main(int argc, char **argv)
    unsigned int offsetValue;
    offsetValue=offset(emp_t,salary);
    printf("field = %s\n","salary");
    printf("offset = %d\n", offsetValue);
    return 0;

如果我编译并运行代码,“salary”字段的偏移量是 20,它应该是 20。 但是,如果我将结构字段char name[20]; 更改为char name[30];,“salary”的偏移量将更改为 32,但它应该是 30。如果我进一步将结构字段更改为 char name[1];,“salary”的偏移量将更改为 4,但它应该是 1. 为什么会出现这些偏移值差异?

问题的第二部分是#define offset 宏究竟是如何计算偏移量的? &(((struct_name *)0)->fld_name) 实际上在做什么?外面的& 表示地址,但剩下的(((struct_name *)0)->fld_name) 到底是什么意思?

【问题讨论】:

它会改变以成为 4 字节对齐(一个 int 的大小) 这不是你的问题,但没有必要定义宏——C在stdlib.h中定义offsetof 确实如此,谢谢@NateEldredge 您问题的第二部分已回答there。另见Wikipedia 【参考方案1】:

对于在您的系统中大小为 4 字节的 unsigned int 类型的对象使用对齐方式。 30 不能被 4 整除,所以在字符数组中追加了两个字节。

考虑以下演示程序。

#include <stdio.h>

int main(void) 

    printf( "sizeof( struct A ) = %zu\n", sizeof( struct A  char c; int x;  ) );
    printf( "sizeof( struct B ) = %zu\n", sizeof( struct B  char c; double d;  ) );

    return 0;

它的输出是

sizeof( struct A ) = 8
sizeof( struct B ) = 16

int 类型的大小等于4double 类型等于8。因此,struct A 类型的对象应由可被 4 整除的边界对齐,而 struct B 的对象应由可被 8 整除的边界对齐。

例如,您可以使用编译器指令打包结构。但在这种情况下,对此类结构的数据成员的访问效率会很低。

【讨论】:

以上是关于如果数组大小发生变化以及定义的宏如何在此处计算偏移量,为啥 C 结构中的字符数组的偏移量会有所不同? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在 RxCocoa/RxSwift 中,如何观察 BehaviorRelay<[object]> 数组大小发生变化

悬停时的不透明度变化会导致图像偏移或失真

C# wpf 如何实现自定义控件,布局时,大小发生变化,内部绘制的曲线跟随变化?

计算结构体的大小

c_cpp 使用地址偏移量包含N个元素的数组成员计算struct的大小

刷新控件和搜索栏导致表格视图/滚动视图出现奇怪的偏移,如何解决?