如果数组大小发生变化,为什么 C 结构中的字符数组的偏移量会发生变化,以及定义的宏如何在此处计算偏移量?
Why Offset varies for character array in C structure if array size changes and how the defined macro is calculating offset here?
我已经定义了一个宏来计算结构到任何结构字段的偏移量。
代码如下:
#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];
,“薪水”的偏移量将更改为 32,但它应该是 30。如果我进一步将结构字段更改为 char name[1];
,“薪水”的偏移量更改为 4 但它应该是 1。为什么会出现这些偏移值差异?
问题的第二部分是 #define offset
宏究竟是如何计算偏移量的? &(((struct_name *)0)->fld_name)
实际上在做什么?外面的 &
表示地址,但剩下的 (((struct_name *)0)->fld_name)
到底是什么意思?
在您的系统中,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 整除的边界对齐。
例如,您可以使用编译器指令打包结构。但在这种情况下访问此类结构的数据成员将是低效的。
我已经定义了一个宏来计算结构到任何结构字段的偏移量。 代码如下:
#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];
,“薪水”的偏移量将更改为 32,但它应该是 30。如果我进一步将结构字段更改为 char name[1];
,“薪水”的偏移量更改为 4 但它应该是 1。为什么会出现这些偏移值差异?
问题的第二部分是 #define offset
宏究竟是如何计算偏移量的? &(((struct_name *)0)->fld_name)
实际上在做什么?外面的 &
表示地址,但剩下的 (((struct_name *)0)->fld_name)
到底是什么意思?
在您的系统中,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 整除的边界对齐。
例如,您可以使用编译器指令打包结构。但在这种情况下访问此类结构的数据成员将是低效的。