<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bitgefummel]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich muss (leider) bitfummelei betreiben und das auch noch mit einem sehr kompliziert definiertem Format. Das Format definiert bit-gepackte Nachrichten, die auch noch variante Felder enthält. Die Nachrichten empfange ich über ein Socket. Beispiel:</p>
<p>NACHRICHT:<br />
- Feld1 von Bit 1 bis Bit 1<br />
- Feld2 von Bit 2 bis Bit 4<br />
- Feld3 von Bit 5 bis Bit 8<br />
- Feld4 von Bit 2 bis Bit 8</p>
<p>Ich dachte, dass ich einfach ein enstprechendes struct definiere, dann mit dem g++-Schalter &quot;__attribute__((packed)) aligne und die empfange Nachricht mit memcpy auf das struct knalle. Anbei mein struct:</p>
<pre><code>struct nachricht_t
{
	// Byte 0
	TYPE field1 : 1;
	union
	{
		struct
		{
			TYPE field2 : 4;
			TYPE field3 : 3;
		} __attribute__((packed));
		TYPE field4 : 7;
	} __attribute__((packed));
} __attribute__((packed));
</code></pre>
<p>Tja, leider ergibt ein</p>
<pre><code>sizeof(nachricht_t)
</code></pre>
<p>2 Byte anstatt des erwarteten 1 Byte.</p>
<p>Hat jemand eine Idee, wie ich das Alignment doch noch hinfummeln kann?</p>
<p>Falls das mit dem Alignment nicht geht, wäre ich auch für einen Alternativvorschlag dankbar. Ich muss dich Nachrichten lesen und auch erzeugen.</p>
<p>Danke schon mal für Hinweise.</p>
<p>Grüße, Vinzent</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/313728/bitgefummel</link><generator>RSS for Node</generator><lastBuildDate>Sat, 01 Aug 2026 18:38:38 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/313728.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 08 Feb 2013 14:42:59 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 14:42:59 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich muss (leider) bitfummelei betreiben und das auch noch mit einem sehr kompliziert definiertem Format. Das Format definiert bit-gepackte Nachrichten, die auch noch variante Felder enthält. Die Nachrichten empfange ich über ein Socket. Beispiel:</p>
<p>NACHRICHT:<br />
- Feld1 von Bit 1 bis Bit 1<br />
- Feld2 von Bit 2 bis Bit 4<br />
- Feld3 von Bit 5 bis Bit 8<br />
- Feld4 von Bit 2 bis Bit 8</p>
<p>Ich dachte, dass ich einfach ein enstprechendes struct definiere, dann mit dem g++-Schalter &quot;__attribute__((packed)) aligne und die empfange Nachricht mit memcpy auf das struct knalle. Anbei mein struct:</p>
<pre><code>struct nachricht_t
{
	// Byte 0
	TYPE field1 : 1;
	union
	{
		struct
		{
			TYPE field2 : 4;
			TYPE field3 : 3;
		} __attribute__((packed));
		TYPE field4 : 7;
	} __attribute__((packed));
} __attribute__((packed));
</code></pre>
<p>Tja, leider ergibt ein</p>
<pre><code>sizeof(nachricht_t)
</code></pre>
<p>2 Byte anstatt des erwarteten 1 Byte.</p>
<p>Hat jemand eine Idee, wie ich das Alignment doch noch hinfummeln kann?</p>
<p>Falls das mit dem Alignment nicht geht, wäre ich auch für einen Alternativvorschlag dankbar. Ich muss dich Nachrichten lesen und auch erzeugen.</p>
<p>Danke schon mal für Hinweise.</p>
<p>Grüße, Vinzent</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297163</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297163</guid><dc:creator><![CDATA[Vinzent72]]></dc:creator><pubDate>Fri, 08 Feb 2013 14:42:59 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 14:54:59 GMT]]></title><description><![CDATA[<p>Hmm...</p>
<pre><code class="language-cpp">#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;

typedef union {
  struct {
    uint8_t field1 : 1;
    uint8_t field4 : 7;
  };

  struct {
    uint8_t implementation_detail_padding : 1;
    uint8_t field2 : 4;
    uint8_t field3 : 3;
  };
} __attribute__((packed)) nachricht_t;

int main(void) {
  printf(&quot;%zu\n&quot;, sizeof(nachricht_t));

  nachricht_t n;

  n.field1 = 1;
  n.field2 = 2;
  n.field3 = 3;

  printf(&quot;%d\n&quot;, n.field1);
  printf(&quot;%d\n&quot;, n.field2);
  printf(&quot;%d\n&quot;, n.field3);
  printf(&quot;%d\n&quot;, n.field4);

  n.field4 = 4;

  printf(&quot;%d\n&quot;, n.field1);
  printf(&quot;%d\n&quot;, n.field2);
  printf(&quot;%d\n&quot;, n.field3);
  printf(&quot;%d\n&quot;, n.field4);

  return 0;
}
</code></pre>
<p>funktioniert bei mir (C99). Ob das in C++ mit anonymen Membern auch vorgesehen ist, weiß ich aus dem Stand nicht.</p>
<p>Btw, deine Beschreibung und dein Code decken sich nicht ganz. Soll field2 jetzt 3 oder 4 Bit haben?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297170</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297170</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Fri, 08 Feb 2013 14:54:59 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 15:22:22 GMT]]></title><description><![CDATA[<p>Ha, das ging ja fix <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Dein Vorschlag mit den zwei structs in der union funktionieren (auch mit dem g++)! Auf die Idee mit dem implementation_detail_padding Feld bin ich nicht gekommen.</p>
<p>Vielen Dank!</p>
<p>Grüße, Vinzent</p>
<p>PS: Hatte die Bits bei field2 und field3 vertauscht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297176</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297176</guid><dc:creator><![CDATA[Vinzent72]]></dc:creator><pubDate>Fri, 08 Feb 2013 15:22:22 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 15:58:15 GMT]]></title><description><![CDATA[<p>Tja, schei...e <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Das oben war natürlich nur ein kurzes Beispiel. Mit der echten Nachricht (message_2_t) klappt es wieder nicht (auch nicht mit dem c-Compiler). Die union ist 12 Byte anstatt der erwarteten 9 Byte. Hier ist wohl das Problem, dass ich zwischendurch größere Typen benötige (uint16_t).</p>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;

typedef union
{
	struct
	{
		uint8_t field1 : 1;
		uint8_t field2 : 4;
		uint8_t field3 : 3;

	};

	struct
	{
		uint8_t field1_padding : 1;
		uint8_t field4 : 7;
	};

} __attribute__((packed)) message_t;

union 
{
	struct
	{
		uint8_t field1 : 2;
		uint8_t field2 : 5;
		uint8_t field3 : 1;
  		uint8_t field4 : 5;
		uint16_t field5 : 12;
		uint16_t field6 : 12;
		uint16_t field7_1 : 11;
		uint8_t field8 : 6;
		uint8_t field9 : 7;
		uint8_t field10 : 8;
		uint8_t field11 : 1;
		uint8_t field12 : 2;
	};

	struct
	{
		uint8_t __field1 : 2;
		uint8_t __field2 : 5;
		uint8_t __field3 : 1;
  		uint8_t __field4 : 5;
		uint16_t __field5 : 12;
		uint16_t __field6 : 12;
		uint8_t field7_2 : 7;
		uint8_t field7_3 : 4;
		uint8_t __field8 : 6;
		uint8_t __field9 : 7;
		uint8_t __field10 : 8;
		uint8_t __field11 : 1;
		uint8_t __field12 : 2;
	};
} __attribute__((packed)) message_2_t;

int main(void)
{
	printf(&quot;%zu\n&quot;, sizeof (message_t));
	printf(&quot;%zu\n&quot;, sizeof (message_2_t));
	return 0;
}
</code></pre>
<p>Hat noch wer eine Idee?</p>
<p>Grüße, Vinzent</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297189</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297189</guid><dc:creator><![CDATA[Vinzent72]]></dc:creator><pubDate>Fri, 08 Feb 2013 15:58:15 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 16:05:47 GMT]]></title><description><![CDATA[<p>Vinzent72 schrieb:</p>
<blockquote>
<p>Hat noch wer eine Idee?</p>
<p>Grüße, Vinzent</p>
</blockquote>
<p>KJa. Erzähnel, WAS DU machen willst, nicht WIE.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297196</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297196</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Fri, 08 Feb 2013 16:05:47 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 16:07:27 GMT]]></title><description><![CDATA[<p>Vinzent72 schrieb:</p>
<blockquote>
<p>Das oben war natürlich nur ein kurzes Beispiel. Mit der echten Nachricht (message_2_t) klappt es wieder nicht (auch nicht mit dem c-Compiler). Die union ist 12 Byte anstatt der erwarteten 9 Byte. Hier ist wohl das Problem, dass ich zwischendurch größere Typen benötige (uint16_t).</p>
</blockquote>
<p>Oder daß die structs nicht packed sind, sondern nur die union.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297197</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297197</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Fri, 08 Feb 2013 16:07:27 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 16:23:43 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>Vinzent72 schrieb:</p>
<blockquote>
<p>Hat noch wer eine Idee?</p>
<p>Grüße, Vinzent</p>
</blockquote>
<p>KJa. Erzähnel, WAS DU machen willst, nicht WIE.</p>
</blockquote>
<p>WAS ich machen möchte ist, Nachrichten (wie oben beschrieben) aus einem Socket lesen und dann verarbeiten (dazu muss ich die Inhalte kennen). Das ganze auch vice versa, d.h. Nachrichten erstellen und über den Socket versenden.</p>
<p>Ich wollte mir das manuelle Bitgefummel (&amp;, |, &lt;&lt;) halt sparen durch entsprechen ausgerichtete ('aligndte' wollt ich jetzt nicht schreiben ;)) structs.</p>
<p>Grüße, Vinzent</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297201</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297201</guid><dc:creator><![CDATA[Vinzent]]></dc:creator><pubDate>Fri, 08 Feb 2013 16:23:43 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 16:31:38 GMT]]></title><description><![CDATA[<p>Eine Mischung aus beidem. Wenn du schreibst</p>
<pre><code class="language-cpp">uint8_t field1 : 2;
        uint8_t field2 : 5;
        uint8_t field3 : 1; // zusammen 8
        uint8_t field4 : 5; // hier 13 -- keine Bytegrenze.
        uint16_t field5 : 12; // Aber hier neuer Typ
        uint16_t field6 : 12;
</code></pre>
<p>hast du die Bruchstelle falsch. Vermieden kriegst du das in diesem Fall nur, indem du alles nach field3 in einen großen uint64_t packst -- sonst liegt immer etwas auf einer Schnittstelle. Damit aber zwischen den uint8_t am Anfang und den uint64_t am Ende kein Padding vom Compiler eingefügt wird, müssen die Structs dann auch packed sein. Also:</p>
<pre><code class="language-cpp">typedef union
{
    struct
    {
        uint8_t field1 : 2;
        uint8_t field2 : 5;
        uint8_t field3 : 1;
        uint64_t field4 : 5;
        uint64_t field5 : 12;
        uint64_t field6 : 12;
        uint64_t field7_1 : 11;
        uint64_t field8 : 6;
        uint64_t field9 : 7;
        uint64_t field10 : 8;
        uint64_t field11 : 1;
        uint64_t field12 : 2;
    } __attribute__((packed));

    struct
    {
        uint8_t __field1 : 2; // __foo sind übrigens für die Implementation reservierte Bezeichner. Du solltest deine unbenutzten Felder anders nennen.
        uint8_t __field2 : 5;
        uint8_t __field3 : 1;
        uint64_t __field4 : 5;
        uint64_t __field5 : 12;
        uint64_t __field6 : 12;
        uint64_t field7_2 : 7;
        uint64_t field7_3 : 4;
        uint64_t __field8 : 6;
        uint64_t __field9 : 7;
        uint64_t __field10 : 8;
        uint64_t __field11 : 1;
        uint64_t __field12 : 2;
    } __attribute__((packed));
} __attribute__((packed)) message_2_t;
</code></pre>
<p>...aber das ist schon ein ziemlich kaputter Datentyp. Ich bin mir nicht sicher, ob so was auf ner SPARC läuft.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297203</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297203</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Fri, 08 Feb 2013 16:31:38 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 16:36:35 GMT]]></title><description><![CDATA[<p>Kürzere Variante:</p>
<pre><code class="language-cpp">typedef union
{
    struct
    {
        uint8_t field1    :  2;
        uint8_t field2    :  5;
        uint8_t field3    :  1;

        uint64_t field4   :  5;
        uint64_t field5   : 12;
        uint64_t field6   : 12;
        uint64_t field7_1 : 11;
        uint64_t field8   :  6;
        uint64_t field9   :  7;
        uint64_t field10  :  8;
        uint64_t field11  :  1;
        uint64_t field12  :  2;
    } __attribute__((packed));

    struct
    {
      uint8_t  implementation_detail_padding_byte;

      uint64_t implementation_detail_padding_vorn : 29;
      uint64_t field7_2 : 7;
      uint64_t field7_3 : 4;
    } __attribute__((packed));
} __attribute__((packed)) message_2_t;
</code></pre>
<p>Auch möglich: das zweite Struct als</p>
<pre><code class="language-cpp">struct
    {
      uint64_t implementation_detail_padding_vorn : 37;
      uint64_t field7_2 : 7;
      uint64_t field7_3 : 4;
    } __attribute__((packed));
</code></pre>
<p>schreiben. Ersteres ist etwas sauberer, wegen Layout-Kompatibilität und so, aber bei so einer Sache ist es etwas müßig, sich um Sauberkeit zu zanken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297205</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297205</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Fri, 08 Feb 2013 16:36:35 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 19:41:25 GMT]]></title><description><![CDATA[<p>seldon schrieb:</p>
<blockquote>
<pre><code class="language-cpp">// __foo sind übrigens für die Implementation reservierte Bezeichner. Du solltest deine unbenutzten Felder anders nennen
</code></pre>
</blockquote>
<p>oder gleich unbenannt lassen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297268</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297268</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 08 Feb 2013 19:41:25 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Fri, 08 Feb 2013 20:29:26 GMT]]></title><description><![CDATA[<p>Structs und Bitfelder auf irgendwelche Daten zu mappen würde ich lassen, weil maschinen und compilerabhängig. Die sicherste Methode ist immer noch, mit Ausmaskieren und Shiften an die Bits zu kommen. Das klappt überall.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297278</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297278</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 08 Feb 2013 20:29:26 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Sat, 09 Feb 2013 11:13:21 GMT]]></title><description><![CDATA[<p>Z schrieb:</p>
<blockquote>
<p>Structs und Bitfelder auf irgendwelche Daten zu mappen würde ich lassen, weil maschinen und compilerabhängig. Die sicherste Methode ist immer noch, mit Ausmaskieren und Shiften an die Bits zu kommen. Das klappt überall.</p>
</blockquote>
<p>Volle Zustimmung!</p>
<p>So schwer muss man sich das auch nicht machen. Man könnte sich z.B. eine &quot;bit_reader&quot;-Klasse bauen, die einem die Dinger aus einer unsigned-char-Sequenz holen. Allerdings müsste man dazu noch wissen, in welcher Reihenfolge die Bits betrachtet werden. Da gibt es im Wesentlichen zwei Varianten, wovon die populärere die höherwertigen Bits zuerst liest.</p>
<p>Weil ich gerade Bock drauf hatte:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;iomanip&gt;
#include &lt;cstdint&gt;
#include &lt;stdexcept&gt;
#include &lt;algorithm&gt;

template&lt;class OctetInputIter&gt;
class bit_reader
{
	OctetInputIter next;
	OctetInputIter end;
	std::uint32_t data;
	unsigned dlen;

	void read_octet()
	{
		if (next==end) throw std::runtime_error(&quot;end of bitstream&quot;);
		data = (data &lt;&lt; 8) | (*next &amp; 0xFFu);
		dlen += 8;
		++next;
	}

public:
	bit_reader(OctetInputIter n, OctetInputIter e)
		: next(n), end(e)
		, data(0), dlen(0)
	{}

	std::uint32_t read(unsigned nbits)
	{
		std::uint32_t result = 0;
		while (nbits&gt;0) {
			while (dlen&lt;nbits &amp;&amp; dlen&lt;=24)
				read_octet();
			// how many bits to move from data to result?
			int chunk = std::min(dlen,nbits);
			dlen -= chunk;
			nbits -= chunk;
			result = (result &lt;&lt; chunk) | (data &gt;&gt; dlen);
			data &amp;= (1u &lt;&lt; dlen) - 1;
		}
		return result;
	}
};

template&lt;class OctetInputIter&gt;
bit_reader&lt;OctetInputIter&gt; make_bit_reader(OctetInputIter begin, OctetInputIter end)
{
	return bit_reader&lt;OctetInputIter&gt;(begin,end);
}

int main()
{
	using namespace std;
	unsigned char dat[] = {0x12,0x34,0x56};
	auto br = make_bit_reader(dat+0,dat+sizeof(dat));
	cout &lt;&lt; hex &lt;&lt; br.read(4) &lt;&lt; endl;
	cout &lt;&lt; hex &lt;&lt; br.read(8) &lt;&lt; endl;
	cout &lt;&lt; hex &lt;&lt; br.read(4) &lt;&lt; endl;
	cout &lt;&lt; hex &lt;&lt; br.read(8) &lt;&lt; endl;
}
</code></pre>
<p>Dieses Beispiel scheint jedenfalls zu funktionieren:</p>
<pre><code>me@compi ~/Documents/ccpp
$ g++ -std=c++0x bit_reader.cpp

me@compi ~/Documents/ccpp
$ a
1
23
4
56
</code></pre>
<p>Ich garantiere nicht dafür, dass da nicht vielleicht noch andere Bugs drin sind. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297365</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297365</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Sat, 09 Feb 2013 11:13:21 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Sat, 09 Feb 2013 13:24:04 GMT]]></title><description><![CDATA[<p>Naja, das hängt jetzt ein bisschen davon ab, was da noch kommt - TE ist bislang mit Details ziemlich zurückhaltend. Es scheint sich um etwas zu handeln, bei dem Platz ziemlich teuer ist -- wenn das Netzwerkverkehr ist, ist es wohl unproblematisch, das beim Lesen einmal auszuklamüsern und in eine vernünftige Form zu bringen, aber wenn das Zeug beispielsweise einem kleinen ARM per UART-DMA oder so übergeben wird, können Speicher und CPU-Zeit ebenfalls knapp sein, und dann könnte es wenig sinnvoll sein, da noch weitere Objekte drumzubasteln.</p>
<p>Aber: Wenn Portabilität gewollt ist, läuft man mit diesem Zeug noch in ganz andere Probleme. Wie sieht das mit 11 Bit breiten Bitfeldern innerhalb eines uint64_t in Bezug auf Bytesex aus? Das ist nicht ganz trivial zu beantworten. Was auf der einen Maschine in Bits 7-18 lag, liegt auf der anderen in Bits...äh...63, 48-56 und 40-42, glaube ich. Das unabhängig davon, ob man mit Bitfeldern arbeitet oder das von Hand herumshiftet (sofern man die Bytes nicht einzeln shiftet und zusammensetzt).</p>
<p>Ein ganz anderes Problem ist noch, dass die Allokation der Bitfelder innerhalb eines Datentyps implementation-defined ist. Ob also die Daten nach dem nächsten Compilerupdate noch an der selben Stelle landen, ist nicht sichergestellt. Wenn da unterschiedliche Versionen miteinander reden sollen oder die Nachrichten irgendwo gespeichert werden, hast du ein echtes Problem.</p>
<p>Ich würde das ganze vermutlich in ein POD-Struct verpacken, das nur die Bytes hält und Methoden zum Zugriff zur Verfügung stellt (ja, PODs dürfen das). Etwa so:</p>
<pre><code class="language-cpp">struct message_t {
  // Alles public, um POD zu bleiben

  unsigned char data;

  uint8_t field1() const { return data      &amp; 0x01; }
  uint8_t field2() const { return data &gt;&gt; 1 &amp; 0x0f; }
  uint8_t field3() const { return data &gt;&gt; 5       ; }
  uint8_t field4() const { return data &gt;&gt; 1       ; }

  void field1(uint8_t x) { data |=  x &amp; 0x01      ; }
  void field2(uint8_t x) { data |= (x &amp; 0x0f) &lt;&lt; 1; }
  void field3(uint8_t x) { data |=  x         &lt;&lt; 5; }
  void field4(uint8_t x) { data |=  x         &lt;&lt; 1; }
} __attribute__((packed));

struct message_2_t {
  unsigned char bytes[9];

  uint8_t  field1() const { return bytes[0]      &amp; 0x03; }
  uint8_t  field2() const { return bytes[0] &gt;&gt; 2 &amp; 0x1f; }
  uint8_t  field3() const { return bytes[0] &gt;&gt; 7       ; }
  uint8_t  field4() const { return bytes[1]      &amp; 0x1f; }
  uint16_t field5() const { return (bytes[1] &gt;&gt; 5) | (bytes[2] &lt;&lt; 3) | ((bytes[3] &amp; 0x01) &lt;&lt; 11); }
  ...      
} __attribute__((packed));
</code></pre>
<p>...das ist zwar ein Haufen Arbeit, dafür funktioniert es am Ende aber überall gleich (wo __attribute__((packed)) existiert). Ob man sich etwas TMP-Kram baut, um die Bitmasken und Shiftlängen vom Compiler ausrechnen zu lassen, ist eine Überlegung wert, und mindestens die Breite mit den Masken zu verknüpfen ist sinnvoll, wenn man zumindest Zweierkomplementdarstellung voraussetzen kann (merke: 0x1f == (1 &lt;&lt; 5) - 1).</p>
<p>Die Arbeit darfste aber selbst machen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297387</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297387</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Sat, 09 Feb 2013 13:24:04 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Mon, 11 Feb 2013 09:20:01 GMT]]></title><description><![CDATA[<p>seldon schrieb:</p>
<blockquote>
<p>Ich würde das ganze vermutlich in ein POD-Struct verpacken, das nur die Bytes hält und Methoden zum Zugriff zur Verfügung stellt (ja, PODs dürfen das).</p>
</blockquote>
<p>Erst mal danke für eure Antworten.</p>
<p>Mit ist schon klar, dass das Bit packing unportabel (gefährlich) ist, aber da ich ca. 250 unterschiedliche solcher Nachrichten zu dekodieren habe, habe ich erst mal nach der am schnellsten zu kodierenden Methode gesucht.</p>
<p>Werde aber wohl nicht um di POD-Struct rumkommen... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Grüße, Vinzent.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297774</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297774</guid><dc:creator><![CDATA[Vinzen72]]></dc:creator><pubDate>Mon, 11 Feb 2013 09:20:01 GMT</pubDate></item><item><title><![CDATA[Reply to Bitgefummel on Mon, 11 Feb 2013 15:04:00 GMT]]></title><description><![CDATA[<p>Vinzen72 schrieb:</p>
<blockquote>
<p>Mit ist schon klar, dass das Bit packing unportabel (gefährlich) ist, aber da ich ca. 250 unterschiedliche solcher Nachrichten zu dekodieren habe, habe ich erst mal nach der am schnellsten zu kodierenden Methode gesucht.</p>
<p>Werde aber wohl nicht um di POD-Struct rumkommen... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
</blockquote>
<p>Ja, 250 verschiedene Nachrichten-Typen sind nervig. Aber ich sehe keine Notwendigkeit für Hacks wie die <em>Bitfeld</em>-Frimelei. Mach das als unsigned char-Array und gut ist. Wenn dir das mit der bit_reader-Klasse nicht gefällt, probier es doch mal <a href="http://ideone.com/5Hon0s" rel="nofollow">damit</a>:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;cstdint&gt;
#include &lt;cassert&gt;

//----------[ generischer Kram ]----------

// extracts a sequence of bits from an unsigned char array
// at arbitrary bit positions (most significant bits first)
std::uint32_t get_bits_msbf(
	const unsigned char data[],
	unsigned bit_offset, unsigned nbits)
{
	// TODO: Diese Implementierung kann man vielleicht noch vereinfachen.
	assert(nbits &lt;= 32);
	if (nbits == 0) return 0u;
	data += bit_offset / 8;
	bit_offset &amp;= 7;
	unsigned tlen = 8 - bit_offset;
	std::uint32_t temp = *data &amp; (0xFFu &gt;&gt; bit_offset);
	if (tlen &gt;= nbits)
		return temp &gt;&gt; (tlen-nbits);
	while (tlen+8 &lt;= nbits) {
		++data;
		temp = (temp &lt;&lt; 8) | (*data &amp; 0xFFu);
		tlen += 8;
	}
	unsigned missing = nbits - tlen;
	if (missing) {
		++data;
		temp = (temp &lt;&lt; missing) | (*data &gt;&gt; (8-missing));
	}
	return temp;
}

template&lt;unsigned BitOffset, unsigned BitLen, class MessageTag=void&gt;
struct field
{
	typedef MessageTag message_tag;
	static const unsigned bit_offset = BitOffset;
	static const unsigned bit_len = BitLen;
};

template&lt;class MessageTag=void&gt;
struct message_ptr
{
	const unsigned char* data;
	unsigned length;

	explicit message_ptr(const unsigned char *ptr, unsigned len)
		: data(ptr), length(len)
	{}

	template&lt;unsigned BitOffset, unsigned BitLen&gt;
	std::uint32_t get(field&lt;BitOffset,BitLen,MessageTag&gt;) const
	{
		assert(BitOffset+BitLen &lt;= 8*length);
		return get_bits_msbf(data,BitOffset,BitLen);
	}
};

//----------[ Anwendungsfall ]----------

namespace mp3_stuff {

struct frame_header_tag {};
const field&lt;0,11,frame_header_tag&gt; sync = {};
const field&lt;11,2,frame_header_tag&gt; mpegid = {};
const field&lt;13,2,frame_header_tag&gt; layer = {};
const field&lt;15,1,frame_header_tag&gt; protection_bit = {};
const field&lt;16,4,frame_header_tag&gt; bitrate_index = {};
const field&lt;20,2,frame_header_tag&gt; sampling_rate_index = {};
const field&lt;22,1,frame_header_tag&gt; padding_bit = {};
const field&lt;23,1,frame_header_tag&gt; private_bit = {};
const field&lt;24,2,frame_header_tag&gt; channel_mode = {};
const field&lt;26,2,frame_header_tag&gt; cm_extension = {};
const field&lt;28,1,frame_header_tag&gt; copyrighted_bit = {};
const field&lt;29,1,frame_header_tag&gt; original_bit = {};
const field&lt;30,2,frame_header_tag&gt; emphasis_mode = {};

static const char* const mpegid2str[] = {&quot;MPEG 2.5&quot;, &quot;reserved&quot;, &quot;MPEG 2&quot;, &quot;MPEG 1&quot;};
static const char* const chanmodes[] = {&quot;Stereo&quot;, &quot;Joint Stereo&quot;, &quot;Dual Channel&quot;, &quot;Mono&quot;};
static const long srate[] = {44100,48000,32000};

} // namespace mp3_stuff

void test()
{
	using namespace std;
	using namespace mp3_stuff;
	unsigned char data[] = {0xFF, 0xFB, 0xA0, 0x64};
	message_ptr&lt;frame_header_tag&gt; mptr (data,4);
	if (mptr.get(sync) == 0x7FF) {
		cout &lt;&lt; &quot;MPEG          : &quot; &lt;&lt; mpegid2str[mptr.get(mpegid)] &lt;&lt; endl;
		cout &lt;&lt; &quot;Layer         : &quot; &lt;&lt; 4-mptr.get(layer) &lt;&lt; endl;
		cout &lt;&lt; &quot;Bitrate index : &quot; &lt;&lt; mptr.get(bitrate_index) &lt;&lt; endl;
		const int srdivisor = 4-mptr.get(mpegid);
		cout &lt;&lt; &quot;Sampling rate : &quot; &lt;&lt; srate[mptr.get(sampling_rate_index)]/srdivisor &lt;&lt; endl;
		cout &lt;&lt; &quot;Channel mode  : &quot; &lt;&lt; chanmodes[mptr.get(channel_mode)] &lt;&lt; endl;
	} else {
		cout &lt;&lt; &quot;Sync bits invalid\n&quot;;
	}
}

int main()
{
	test();
}
</code></pre>
<p>Ich denke, damit sollte die Fehleranfälligkeit in der Benutzung nicht so groß sein. Man definiert das Format quasi an einer Stelle und überall sonst kann man nicht mehr viel falsch machen, da man per mptr.get(feld) ein Datum ausliest, siehe Zeilen 92-98. Aufgrund des MessageTag-Parameters sollte das auch genügend typsicher sein.</p>
<p>Was mit gerade auffällt: Es macht ja sogar Sinn, statt <code>get</code> den <code>operator-&gt;*</code> zu überladen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2297900</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2297900</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Mon, 11 Feb 2013 15:04:00 GMT</pubDate></item></channel></rss>