1

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

#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];“工资”的偏移更改为 4,但它应该是 1。为什么会发生这些偏移值差异?

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

4

1 回答 1

2

unsigned int对于系统中大小为 4 字节的类型的对象,使用对齐方式。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的大小等于 ,4类型double等于8。因此,结构 A 类型的对象应与可被 4 整除的边界对齐,而结构 B 的对象应与可被 8 整除的边界对齐。

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

于 2021-02-18T18:21:01.207 回答