<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
	<id>https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=Offsetof</id>
	<title>Offsetof - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=Offsetof"/>
	<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=Offsetof&amp;action=history"/>
	<updated>2026-07-10T06:05:47Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://arolstar52-zhtest.hf.space/index.php?title=Offsetof&amp;diff=2975974&amp;oldid=prev</id>
		<title>imported&gt;潜水飞机：​更正链接</title>
		<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=Offsetof&amp;diff=2975974&amp;oldid=prev"/>
		<updated>2020-12-25T17:57:50Z</updated>

		<summary type="html">&lt;p&gt;更正链接&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{lowercase}}&lt;br /&gt;
{{NoteTA&lt;br /&gt;
|G1 = IT&lt;br /&gt;
|1 = zh-cn:宏; zh-tw:巨集;&lt;br /&gt;
}}&lt;br /&gt;
[[C语言]]的&amp;#039;&amp;#039;&amp;#039;&amp;lt;tt&amp;gt;offsetof()&amp;lt;/tt&amp;gt;&amp;#039;&amp;#039;&amp;#039;宏，是定义在&amp;lt;tt&amp;gt;[[stddef.h]]&amp;lt;/tt&amp;gt;。用于求出一个[[结构体_(C语言)|struct]]或[[联合体|union]]数据类型的给定成员的&amp;lt;tt&amp;gt;[[size_t]]&amp;lt;/tt&amp;gt;类型的字节偏移值。&amp;lt;tt&amp;gt;offsetof()&amp;lt;/tt&amp;gt;宏有两个参数，分别是结构名与结构内的成员名。不能声明为C原型。&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
| url = http://msdn.microsoft.com/en-us/library/dz4y9b9a.aspx&lt;br /&gt;
| publisher = [[MSDN]]&lt;br /&gt;
| title = offsetof reference&lt;br /&gt;
| accessdate = 2010-09-19&lt;br /&gt;
| archive-date = 2011-10-10&lt;br /&gt;
| archive-url = https://web.archive.org/web/20111010130120/http://msdn.microsoft.com/en-us/library/dz4y9b9a.aspx&lt;br /&gt;
| dead-url = no&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==实现==&lt;br /&gt;
传统实现依赖于编译器对指针不是很挑剔。它假定结构的地址为0，然后获得成员的偏移值：&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define offsetof(st, m) ((size_t)&amp;amp;(((st *)0)-&amp;gt;m))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
上述定义在[[C11]]语言标准下是[[未定义行为]]，&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
|url=https://stackoverflow.com/questions/26906621/does-struct-name-null-b-cause-undefined-behaviour-in-c11&lt;br /&gt;
|title=Does &amp;amp;((struct name *)NULL -&amp;gt; b) cause undefined behaviour in C11?&lt;br /&gt;
|accessdate=2015-02-07&lt;br /&gt;
|archive-date=2015-02-07&lt;br /&gt;
|archive-url=https://web.archive.org/web/20150207105717/http://stackoverflow.com/questions/26906621/does-struct-name-null-b-cause-undefined-behaviour-in-c11&lt;br /&gt;
|dead-url=no&lt;br /&gt;
}}&amp;lt;/ref&amp;gt; 因为它对空指针做了解引用（dereference）。[[GCC]]现在定义该宏为：&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
| url = https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Offsetof.html&lt;br /&gt;
| title = GCC offsetof reference&lt;br /&gt;
| publisher = [[Free Software Foundation]]&lt;br /&gt;
| accessdate = 2010-09-19&lt;br /&gt;
| archive-date = 2010-07-24&lt;br /&gt;
| archive-url = https://web.archive.org/web/20100724235737/http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Offsetof.html&lt;br /&gt;
| dead-url = no&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define offsetof(st, m) __builtin_offsetof(st, m)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
这种内置对C++的&amp;lt;tt&amp;gt;class&amp;lt;/tt&amp;gt;或&amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt;也适用。&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
| url = https://stackoverflow.com/questions/400116/what-is-the-purpose-and-return-type-of-the-builtin-offsetof-operator/406941#406941&lt;br /&gt;
| title = what is the purpose and return type of the __builtin_offsetof operator?&lt;br /&gt;
| accessdate = 2012-10-20&lt;br /&gt;
| archive-date = 2014-12-15&lt;br /&gt;
| archive-url = https://web.archive.org/web/20141215044302/http://stackoverflow.com/questions/400116/what-is-the-purpose-and-return-type-of-the-builtin-offsetof-operator/406941#406941&lt;br /&gt;
| dead-url = no&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==用途==&lt;br /&gt;
[[Linux内核]]使用&amp;lt;tt&amp;gt;offsetof()&amp;lt;/tt&amp;gt;来实现&amp;lt;tt&amp;gt;container_of()&amp;lt;/tt&amp;gt;，这允许类似于[[mixin]]类型以发现包含它的结构:&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
| url = http://www.kroah.com/log/linux/container_of.html&lt;br /&gt;
| title = &amp;lt;tt&amp;gt;container_of()&amp;lt;/tt&amp;gt;&lt;br /&gt;
| author = Greg Kroah-Hartman&lt;br /&gt;
| publisher = [[Linux Journal]]&lt;br /&gt;
| date = June 2003&lt;br /&gt;
| accessdate = 2010-09-19&lt;br /&gt;
| archive-date = 2010-02-13&lt;br /&gt;
| archive-url = https://web.archive.org/web/20100213091627/http://www.kroah.com/log/linux/container_of.html&lt;br /&gt;
| dead-url = no&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define container_of(ptr, type, member) ({ \&lt;br /&gt;
                const typeof( ((type *)0)-&amp;gt;member ) *__mptr = (ptr); \&lt;br /&gt;
                (type *)( (char *)__mptr - offsetof(type,member) );})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;container_of()&amp;lt;/tt&amp;gt;宏被用于从指向内嵌成员的指针获得外包的结构的指针。如链表&amp;lt;tt&amp;gt;my_struct&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct my_struct {&lt;br /&gt;
    const char *name;&lt;br /&gt;
    struct list_node list;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
extern struct list_node * list_next(struct list_node *);&lt;br /&gt;
&lt;br /&gt;
struct list_node *current = /* ... */&lt;br /&gt;
while(current != NULL){&lt;br /&gt;
    struct my_struct *element = container_of(current, struct my_struct, list);&lt;br /&gt;
    printf(&amp;quot;%s\n&amp;quot;, element-&amp;gt;name);&lt;br /&gt;
    current = list_next(&amp;amp;element-&amp;gt;list);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Linux内核实现&amp;lt;tt&amp;gt;container_of()&amp;lt;/tt&amp;gt;时，使用了GNU C扩展&amp;#039;&amp;#039;statement expressions&amp;#039;&amp;#039;.&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
| url = https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html&lt;br /&gt;
| title = Statements and Declarations in Expressions&lt;br /&gt;
| publisher = [[Free Software Foundation]]&lt;br /&gt;
| accessdate = 2016-01-01&lt;br /&gt;
| archive-date = 2016-01-05&lt;br /&gt;
| archive-url = https://web.archive.org/web/20160105221853/http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html&lt;br /&gt;
| dead-url = no&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;下述实现也能确保类型安全:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define container_of(ptr, type, member) ((type *)((char *)(1 ? (ptr) : &amp;amp;((type *)0)-&amp;gt;member) - offsetof(type, member)))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
粗看起来，上述的不寻常的?:条件运算符是不适当的。可以写成更简单的形式:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这种写法忽略了检查ptr的类型是否是member的类型，而Linux内核的实现需要这种安全检查。而?:条件运算符要求如果操作数是一个类型的两个指针值，那么它们应当是兼容的类型。所以第三个操作数虽然不会被使用，但编译器要检查&amp;lt;code&amp;gt;(ptr)&amp;lt;/code&amp;gt;与&amp;lt;code&amp;gt;&amp;amp;((type *)0)-&amp;gt;member&amp;lt;/code&amp;gt;是不是兼容的指针类型。&lt;br /&gt;
&lt;br /&gt;
==局限性==&lt;br /&gt;
C++03要求&amp;lt;tt&amp;gt;offsetof&amp;lt;/tt&amp;gt;限于[[POD_(程序设计)|POD]]类型。[[C++11]]要求&amp;lt;tt&amp;gt;offsetof&amp;lt;/tt&amp;gt;限于[[标准布局类型]]，&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
| url = http://www.cplusplus.com/reference/cstddef/offsetof&lt;br /&gt;
| title = &amp;lt;tt&amp;gt;offsetof reference&amp;lt;/tt&amp;gt;&lt;br /&gt;
| publisher = [[cplusplus.com]]&lt;br /&gt;
| accessdate = 2016-04-01&lt;br /&gt;
| archive-date = 2016-03-30&lt;br /&gt;
| archive-url = https://web.archive.org/web/20160330195954/http://www.cplusplus.com/reference/cstddef/offsetof/&lt;br /&gt;
| dead-url = no&lt;br /&gt;
}}&amp;lt;/ref&amp;gt; 但仍存在未定义行为。特别是[[虚继承]]情形。&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
| url = https://stackoverflow.com/a/1130760&lt;br /&gt;
| title = &amp;lt;tt&amp;gt;Why can&amp;#039;t you use offsetof on non-POD structures in C&amp;lt;/tt&amp;gt;&lt;br /&gt;
| author = Steve Jessop&lt;br /&gt;
| publisher = [[Stack Overflow]]&lt;br /&gt;
| date = July 2009&lt;br /&gt;
| accessdate = 2016-04-01&lt;br /&gt;
| archive-date = 2019-10-19&lt;br /&gt;
| archive-url = https://web.archive.org/web/20191019011135/https://stackoverflow.com/questions/1129894/why-cant-you-use-offsetof-on-non-pod-structures-in-c/1130760&lt;br /&gt;
| dead-url = no&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
下述代码用gcc 4.7.3 amd64编译器，产生的结果是有问题的:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stddef.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct A&lt;br /&gt;
{&lt;br /&gt;
    int  a;&lt;br /&gt;
    virtual void dummy() {}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct B: public virtual A&lt;br /&gt;
{&lt;br /&gt;
    int  b;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    printf(&amp;quot;offsetof(A,a) : %zu\n&amp;quot;, offsetof(A, a));&lt;br /&gt;
    printf(&amp;quot;offsetof(B,b) : %zu\n&amp;quot;, offsetof(B, b));&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Output is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
offsetof(A,a) : 8&lt;br /&gt;
offsetof(B,b) : 8&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==参考文献==&lt;br /&gt;
{{reflist}}&lt;br /&gt;
&lt;br /&gt;
[[Category:C標準函式庫]]&lt;/div&gt;</summary>
		<author><name>imported&gt;潜水飞机</name></author>
	</entry>
</feed>