<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>#blogdump &#187; magic macro</title>
	<atom:link href="http://aandre.evolix.net/tag/magic-macro/feed/" rel="self" type="application/rss+xml" />
	<link>http://aandre.evolix.net</link>
	<description>geeky lines</description>
	<lastBuildDate>Wed, 17 Jun 2009 15:43:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>container_of</title>
		<link>http://aandre.evolix.net/2009/06/02/container_of/</link>
		<comments>http://aandre.evolix.net/2009/06/02/container_of/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 13:56:47 +0000</pubDate>
		<dc:creator>arno</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[magic macro]]></category>

		<guid isPermaLink="false">http://aandre.evolix.net/?p=274</guid>
		<description><![CDATA[container_of est une macro très utile et définie dans le kernel linux (./include/linux/kernel.h), qui permet de récupérer l&#8217;adresse d&#8217;une structure à partir d&#8217;un de ses membres:

/*!
* container_of - cast a member of a descriptor out to the containing descriptor
*
* @ptr:    the pointer to the member.
* @type:    the type of [...]]]></description>
			<content:encoded><![CDATA[<p><strong>container_of</strong> est une macro très utile et définie dans le kernel linux (<em>./include/linux/kernel.h</em>), qui permet de récupérer l&#8217;adresse d&#8217;une structure à partir d&#8217;un de ses membres:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/*!
* container_of - cast a member of a descriptor out to the containing descriptor
*
* @ptr:    the pointer to the member.
* @type:    the type of the container struct this is embedded in.
* @member:    the name of the member within the struct.
*
*/</span>
<span style="color: #339933;">#define container_of(ptr, type, member) ({			\</span>
<span style="color: #993333;">const</span> typeof<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>type <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>member <span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span>__mptr <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>ptr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	\
<span style="color: #009900;">&#40;</span>type <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>__mptr <span style="color: #339933;">-</span> offsetof<span style="color: #009900;">&#40;</span>type<span style="color: #339933;">,</span>member<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p>Elle prend en paramètres (comme décrit plus haut):</p>
<ul>
<li><strong>ptr</strong>: le pointeur que nous manipulons, membre de la structure instanciée dont nous voulons récupérer l&#8217;adresse</li>
<li><strong>type</strong>: le type de la structure qui contient ce membre,</li>
<li><strong>member</strong>: le nom du membre dans la déclaration de la structure.</li>
</ul>
<p>La premiere ligne de la macro permet de déclarer un pointeur qui va contenir l&#8217;adresse du membre.</p>
<p>Ce pointeur va être correctement déclaré grâce au cast réalisé par:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">typeof<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>type <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>member <span style="color: #009900;">&#41;</span><span style="color: #339933;">*</span></pre></div></div>

<p>(type *) 0 permet de déclarer un pointeur de structure de type (type) à l&#8217;adresse <strong>0</strong>. On récupère alors le membre qui nous intéresse et plus précisément son type avec <strong>typeof</strong>, opérateur unaire comme <strong>sizeof</strong> défini par <strong>gcc</strong> (<a title="Typeof" href="http://gcc.gnu.org/onlinedocs/gcc/Typeof.html" target="_self">http://gcc.gnu.org/onlinedocs/gcc/Typeof.html</a>).</p>
<p>La deuxième ligne peut se décomposer en deux parties:</p>
<p><span id="more-274"></span></p>
<ul>
<li>offsetof(type, member) va calculer le décalage du champ <strong>member</strong> à partir du début de la structure <strong>type</strong>, en octet. <strong>offsetof (3)</strong> est une macro définie dans <em>stddef.h</em>,</li>
<li>on soustrait à l&#8217;adresse contenue par <strong>__mptr</strong> l&#8217;offset calculé par offsetof. On caste <strong>__mptr</strong> en <em>(char *)</em> afin que la soustraction soit effectuée en octet (sinon le compilateur fixera comme unité la taille du membre <strong>member</strong>).</li>
</ul>
<p>L&#8217;adresse retournée est donc l&#8217;adresse de la structure contenant le membre <strong>ptr</strong>.</p>
<p>Prenons un exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> toto <span style="color: #009900;">&#123;</span>
<span style="color: #993333;">char</span> a<span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> b<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>À un instant t dans mon code, je manipule un pointeur sur le membre <strong>b</strong> d&#8217;une structure <strong>toto</strong> instanciée préalablement en mémoire: <strong>(char *)ptr_sur_b</strong>;<br />
Je n&#8217;ai plus dans le contexte de la fonction l&#8217;adresse de cette structure et pour une raison quelconque (par exemple accéder au membre a) je veux récupérer cette adresse:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> toto <span style="color: #339933;">*</span>t<span style="color: #339933;">;</span>
<span style="color: #808080; font-style: italic;">/* je récupère l'adresse de la structure grâce à containerof */</span>
t <span style="color: #339933;">=</span> containerof<span style="color: #009900;">&#40;</span>ptr_sur_b<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> toto<span style="color: #339933;">,</span> b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #808080; font-style: italic;">/* je peux alors accéder au membre a de la structure t: t-&gt;a */</span></pre></div></div>

<p>Si l&#8217;on remplace <strong>member</strong> et <strong>type</strong> dans la macro par ce qui nous intéresse ici:</p>
<p>ligne 1:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">const</span> typeof<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>type <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>member <span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span>__mptr <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>ptr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">=&gt;</span> <span style="color: #993333;">const</span> typeof <span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> toto<span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>b <span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span>__mptr<span style="color: #339933;">;</span>
<span style="color: #339933;">=&gt;</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>__mptr<span style="color: #339933;">;</span></pre></div></div>

<p>ligne 2:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> toto <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>__mptr <span style="color: #339933;">-</span> offsetof <span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> toto<span style="color: #339933;">,</span> b<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> toto <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> __mptr <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>On retrouvera entre autre l&#8217;utilisation de cette macro dans l&#8217;implémentation des listes (<em>./include/linux/list.h</em>) du kernel.</p>
]]></content:encoded>
			<wfw:commentRss>http://aandre.evolix.net/2009/06/02/container_of/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
