我在互联网上读到了这个偏移宏,但它没有解释它的用途.
#define offsetof(a,b) ((int)(&(((a*)(0))->b)))
Run Code Online (Sandbox Code Playgroud)
它想做什么以及使用它有什么好处?
Eam*_*ain 32
R ..在回答问题的第二部分时是正确的:使用现代C编译器时不建议使用此代码.
但要回答你问题的第一部分,这实际上是做什么的:
(
(int)( // 4.
&( ( // 3.
(a*)(0) // 1.
)->b ) // 2.
)
)
Run Code Online (Sandbox Code Playgroud)
从内到外,这是......
a*b字段的地址int从概念上讲,这是将一个struct对象放在内存地址为零,然后找出特定字段的地址是什么.这可以让您找出结构中每个字段的内存偏移量,这样您就可以编写自己的序列化器和反序列化器来将结构转换为字节数组.
当然,如果您实际取消引用零指针,程序将崩溃,但实际上一切都在编译器中发生,并且在运行时没有实际的零指针被取消引用.
在大多数原始系统中,C运行的大小int为32位且与指针相同,所以这实际上有效.
R..*_*R.. 13
它没有优点,不应该使用,因为它调用未定义的行为(并使用错误的类型 - int而不是size_t).
对于需要结构中元素偏移的情况,C标准定义了一个实际适用的offsetof宏stddef.h,例如:
#include <stddef.h>
struct foo {
int a;
int b;
char *c;
};
struct struct_desc {
const char *name;
int type;
size_t off;
};
static const struct struct_desc foo_desc[] = {
{ "a", INT, offsetof(struct foo, a) },
{ "b", INT, offsetof(struct foo, b) },
{ "c", CHARPTR, offsetof(struct foo, c) },
};
Run Code Online (Sandbox Code Playgroud)
这将允许您以编程方式填充struct foo按名称的字段,例如,在读取JSON文件时.
它正在查找中特定成员的字节偏移量struct。例如,如果您具有以下结构:
struct MyStruct
{
double d;
int i;
void *p;
};
Run Code Online (Sandbox Code Playgroud)
然后,您将拥有offsetOf(MyStruct, d) == 0,offsetOf(MyStruct, i) == 8和offsetOf(MyStruct, p) == 12(即,d从结构的开头开始,名为的成员为0个字节,等等)。
它的工作方式是假装您的结构实例存在于地址0(该((a*)(0))部分),然后获取所需结构成员的地址并将其转换为整数。尽管在地址0处取消引用对象通常是一个错误,但可以采用该地址,因为address-of运算符&和成员取消引用会->相互抵消。
它通常用于广义序列化框架。如果您有用于在某种有线数据(例如,文件中的字节或来自网络的字节)和内存中数据结构之间进行转换的代码,则通常很方便地创建从成员名称到成员偏移的映射,以便您可以序列化或以通用方式反序列化值。
| 归档时间: |
|
| 查看次数: |
13338 次 |
| 最近记录: |