<?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[Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen]]></title><description><![CDATA[<p>Ich habe einen unsigned char array, der rohe bytedaten enthält, die aus einer datei gelesen werden. Davon will ich in shorts lesen, also 2-byte-Stücke.</p>
<p>Die ersten 2 Elemente im uc-Array sind &quot;0&quot; und &quot;21&quot;. D.h. wenn ich das in ein short speichern will, soll da auch wieder 21 rauskommen. Ich mach das so:</p>
<pre><code class="language-cpp">unsigned char *array[...] = ...;

//.. irgendwo anders
unsigned short value = *(unsigned short*)array; //sollte die ersten 2 byte als short auslesen
</code></pre>
<p>Allerdings produziert der Code nicht die erwartete 21, sondern in value steht dann &quot;5376&quot;. Wenn man sich die Zahl binär anschaut (10101000.00000000) sieht die der 21 auch irgendwie ähnlich (00000000.00010101), aber wie man sieht wird hier die Byte-Order vertauscht.</p>
<p>Das ganze läuft auf einem i7, falls euch die Byte-Order des Prozessors hilft.</p>
<p>Kann ich die Byte Order des ausgelesenen Wertes jetzt irgendwie schnell umdrehen, oder durch einen Cast den Code dazu bringen die ersten zwei Elemente in einer anderen Byte-Order auszulesen?</p>
<p>Das hier passiert dabei an einer sehr performanceintensiven Stelle (das wird alles ~ 6 millionen mal gemacht), weshalb es möglichst schnell sein sollte.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/311701/casten-von-array-um-bestimmten-wert-rauszulesen-gt-byteorder-tauschen</link><generator>RSS for Node</generator><lastBuildDate>Sat, 01 Aug 2026 08:55:30 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/311701.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 12 Dec 2012 11:18:22 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Wed, 12 Dec 2012 11:18:22 GMT]]></title><description><![CDATA[<p>Ich habe einen unsigned char array, der rohe bytedaten enthält, die aus einer datei gelesen werden. Davon will ich in shorts lesen, also 2-byte-Stücke.</p>
<p>Die ersten 2 Elemente im uc-Array sind &quot;0&quot; und &quot;21&quot;. D.h. wenn ich das in ein short speichern will, soll da auch wieder 21 rauskommen. Ich mach das so:</p>
<pre><code class="language-cpp">unsigned char *array[...] = ...;

//.. irgendwo anders
unsigned short value = *(unsigned short*)array; //sollte die ersten 2 byte als short auslesen
</code></pre>
<p>Allerdings produziert der Code nicht die erwartete 21, sondern in value steht dann &quot;5376&quot;. Wenn man sich die Zahl binär anschaut (10101000.00000000) sieht die der 21 auch irgendwie ähnlich (00000000.00010101), aber wie man sieht wird hier die Byte-Order vertauscht.</p>
<p>Das ganze läuft auf einem i7, falls euch die Byte-Order des Prozessors hilft.</p>
<p>Kann ich die Byte Order des ausgelesenen Wertes jetzt irgendwie schnell umdrehen, oder durch einen Cast den Code dazu bringen die ersten zwei Elemente in einer anderen Byte-Order auszulesen?</p>
<p>Das hier passiert dabei an einer sehr performanceintensiven Stelle (das wird alles ~ 6 millionen mal gemacht), weshalb es möglichst schnell sein sollte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2279466</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279466</guid><dc:creator><![CDATA[caster_caster]]></dc:creator><pubDate>Wed, 12 Dec 2012 11:18:22 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Wed, 12 Dec 2012 11:23:07 GMT]]></title><description><![CDATA[<p>Übrigens, was mir sehr merkwürdig aufgefallen ist:</p>
<p>Wenn ich das zweite Byte manuell auslese, dann kommt auch wie erwartet die 21 raus. Wird hier wirklich nur die BYTE-reihenfolge vertauscht, und nicht die bit-reihenfolge? Das Ergebnis im Eingangspost hat ja auch eine vertauschte Bit-Order im Byte, das 21 sein sollte. Wenn ich array[1] manuell lese, kommt aber trotzdem 21 raus und nicht eine zu erwartende (mit bits vertauscht) 84.</p>
<p>Woran liegt das? Mache ich hier etwas falsch?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2279467</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279467</guid><dc:creator><![CDATA[caster_caster]]></dc:creator><pubDate>Wed, 12 Dec 2012 11:23:07 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Wed, 12 Dec 2012 11:43:26 GMT]]></title><description><![CDATA[<p>Die CPU kann Bits nicht einzeln adressieren; die Reihenfolge, in der die Bits gespeichert sind, ist daher Ansichtssache. Die Bytereihenfolge ist von Architektur zu Architektur unterschiedlich; ein handelsüblicher PC (d. h. x86 bzw. x86-64) bzw. seine Instructions interpretieren Zahlen als little-endian, also mit dem niederwertigsten Byte vorn. Ein 4-Byte-Integer (32-Bit-Integer) mit dem Wert 258 wird durch die Byte-Folge &quot;2 1 0 0&quot; dargestellt, ein 16-Bit-Integer mit gleichem Wert durch &quot;2 1&quot;. Das ist genau umgedreht von der Schreibweise, die man von Papier gewohnt ist.</p>
<p>Andere Prozessorarchitekturen benutzen big-endian (also Papierschreibweise), und historisch gab es eine Reihe von Middle-Endian-Varianten, die das quer durcheinander würfeln. Siehe auch <a href="https://de.wikipedia.org/wiki/Byte-Reihenfolge" rel="nofollow">https://de.wikipedia.org/wiki/Byte-Reihenfolge</a></p>
<p>Die Lösung deines Problems dürfte ntohs sein, siehe <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ntohl.html" rel="nofollow">http://pubs.opengroup.org/onlinepubs/9699919799/functions/ntohl.html</a> (POSIX) bzw. <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms740075.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/windows/desktop/ms740075.aspx</a> (Windows).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2279469</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279469</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Wed, 12 Dec 2012 11:43:26 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Wed, 12 Dec 2012 11:44:29 GMT]]></title><description><![CDATA[<p>deine Datei hat eine BigEndian Byteordner, während dein Betriebssystem LittleEndian benutzt</p>
<p>greetz KN4CK3R</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2279470</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279470</guid><dc:creator><![CDATA[KN4CK3R]]></dc:creator><pubDate>Wed, 12 Dec 2012 11:44:29 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Wed, 12 Dec 2012 11:49:30 GMT]]></title><description><![CDATA[<p>Schau dir die Zahlen mal in Hex an:<br />
__21<sub>10</sub> = 0015<sub>16</sub><br />
5376<sub>10</sub> = 1500<sub>16</sub><br />
Da kannst du das besser sehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2279472</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279472</guid><dc:creator><![CDATA[DirkB]]></dc:creator><pubDate>Wed, 12 Dec 2012 11:49:30 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Wed, 12 Dec 2012 11:51:22 GMT]]></title><description><![CDATA[<p>Was hälst du denn hiervon?</p>
<pre><code>short to_short(unsigned char* b) 
{
	short i = 0;
	i |= b[0] &amp; 0xFF;
	i &lt;&lt;= 8;
	i |= b[1] &amp; 0xFF;
	return i;
}
int main()
{
	unsigned char bytes[] = &quot;\0\1\2\3&quot;;
	unsigned char* b = bytes;

	for(unsigned i=0; i&lt;sizeof(bytes)/2; ++i)
	{
		cout &lt;&lt; to_short(b) &lt;&lt; '\n';
		b += 2;
	}
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2279473</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279473</guid><dc:creator><![CDATA[out]]></dc:creator><pubDate>Wed, 12 Dec 2012 11:51:22 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Wed, 12 Dec 2012 20:43:13 GMT]]></title><description><![CDATA[<p>caster_caster schrieb:</p>
<blockquote>
<p>Kann ich die Byte Order des ausgelesenen Wertes jetzt irgendwie schnell umdrehen, oder durch einen Cast den Code dazu bringen die ersten zwei Elemente in einer anderen Byte-Order auszulesen?</p>
<p>Das hier passiert dabei an einer sehr performanceintensiven Stelle (das wird alles ~ 6 millionen mal gemacht), weshalb es möglichst schnell sein sollte.</p>
</blockquote>
<p>Es gibt eine Grundregel beim Lesen, die lautet: Lese das, was Du haben willst.<br />
Wenn Du also <code>short</code> willst, so lese doch <code>short</code> s, das <code>unsigned char array</code> ist schlicht überflüssig. Lesen und Schreiben macht man in C++ mit Streams, und da der std::istream nur für das Lesen von Texten gemacht ist, schreibe man sich selbst einen Stream, der binär liest. Das ist gar nicht so schwer, wie es vielleicht im ersten Moment scheint - wie bei so vielen Dingen, man muss halt wissen wie's geht.</p>
<p>Solange es bei den <code>short</code> s bleibt mit Wechsel des Endians, reicht folgendes aus:</p>
<pre><code>#include &lt;algorithm&gt; // std::reverse, std::swap
#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;streambuf&gt;
#include &lt;cassert&gt;

class ibinstream : public std::basic_ios&lt; char &gt;
{
    typedef std::basic_ios&lt; char &gt; base_type;
public:
    explicit ibinstream( std::streambuf* sb = 0 )
        : base_type( sb )
    {}

    ibinstream&amp; operator&gt;&gt;( short&amp; s )
    {
        if( good() )
        {
            std::ios_base::iostate state = std::ios_base::goodbit; // state = good;
            try
            {
                if( rdbuf()-&gt;sgetn( reinterpret_cast&lt; char* &gt;( &amp;s ), std::streamsize( sizeof(s) ) ) == std::streamsize( sizeof(s) ) )
                {
                    // ok - gewünschte Bytes sind gelesen
                    assert( sizeof(s) == 2 ); // sonst: reverse( reinterpret_cast&lt; char* &gt;( &amp;s ), reinterpret_cast&lt; char* &gt;( &amp;s ) + sizeof( s ) );
                    std::swap( *reinterpret_cast&lt; char* &gt;( &amp;s ), *(reinterpret_cast&lt; char* &gt;( &amp;s )+1) ); // Endian wechseln
                }
                else
                    state |= std::ios_base::eofbit | std::ios_base::failbit;
            }
            catch( ... )
            {
                state |= std::ios_base::badbit;
                if( exceptions() &amp; std::ios_base::badbit )
                    throw;
            }
            setstate( state );
        }
        return *this;
    }
};

int main()
{
    using namespace std;
    ifstream file(&quot;egal.bin&quot;, ios_base::binary ); // mode == binary!
    if( !file.is_open() )
    {
        cerr &lt;&lt; &quot;Fehler beim Oeffnen&quot; &lt;&lt; endl;
        return -2;
    }

    ibinstream in( file.rdbuf() ); // ibinstream über den File-Buffer 'stülpen'
    int cnt = 0;
    for( short s; in &gt;&gt; s; ) // lesen bis EOF
        ++cnt; // hier kann das short 's' verarbeitet werden
    cout &lt;&lt; cnt &lt;&lt; &quot;short gelesen&quot; &lt;&lt; endl;

    return 0;
}
</code></pre>
<p>Die Geschwindigkeit liegt bei mir knapp unter 100MByte/s (inklusive Einlesen von Platte) - die 6MByte sollten also in weniger als 0,1s erledigt sein.</p>
<p>Mehr Beispiel für ibinstream gibt es <a href="http://www.c-plusplus.net/forum/p2201290#2201290" rel="nofollow">hier</a> &amp; <a href="http://www.c-plusplus.net/forum/p1561419#1561419" rel="nofollow">hier</a>.</p>
<p>out schrieb:</p>
<blockquote>
<p>Was hälst du denn hiervon?</p>
<pre><code>short to_short(unsigned char* b) 
{
    ...
</code></pre>
</blockquote>
<p>Mit Verlaub - gar nichts. Ich kenne diesen Code .. klein und harmlos mit Dateien von ein paar Byte mag das ok sein. Hat man Dateien von mehreren 10 oder 100kByte und verteilen sich die Aufrufe von to_short über die Applikation, bekommt man große Probleme. Nirgends ist mehr klar, ob das to_short bereits aufgerufen wurde oder noch nicht.<br />
Wenn bei oben erwähnter Applikation nur all das Geld, was für die Pflege und Bugfixes von 'to_short' und 'to_dword' und .. aufgewendet wurde, auf meinen Konto wäre, käme leicht ein Jahresgehalt zusammen!<br />
Für professionellen Code ist das ein NO-GO!</p>
<p>:xmas2: Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2279597</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279597</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Wed, 12 Dec 2012 20:43:13 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Wed, 12 Dec 2012 23:19:21 GMT]]></title><description><![CDATA[<p>Werner Salomon schrieb:</p>
<blockquote>
<p>Hat man Dateien von mehreren 10 oder 100kByte und verteilen sich die Aufrufe von to_short über die Applikation, bekommt man große Probleme. Nirgends ist mehr klar, ob das to_short bereits aufgerufen wurde oder noch nicht.</p>
</blockquote>
<p>An der miesen Aufteilung des Programms ist also <code>to_short</code> schuld?<br />
Ein <code>short</code> ist ein <code>short</code> . Wie soll da nicht klar sein, ob <code>to_short</code> schon erfolgt ist?</p>
<p>Werner Salomon schrieb:</p>
<blockquote>
<p>Für professionellen Code ist das ein NO-GO!</p>
</blockquote>
<p>Ein NO-GO ist implementationsabhängiges Verhalten durch <code>reinterpret_cast</code> -Gefrickel. Es hat schon seinen Grund, dass so etwas fast immer als unangebracht gilt.</p>
<p>Für all die Profis was zu lesen: <a href="http://commandcenter.blogspot.de/2012/04/byte-order-fallacy.html" rel="nofollow">The byte order fallacy</a></p>
<p><code>to_short</code> macht es im Prinzip schon richtig.</p>
<pre><code class="language-cpp">//vernünftiger Name, const, das unnötige unsigned weg
short read_big_endian_short(const char *b)
{
    short i = 0;
    i |= b[0];
    i &lt;&lt;= 8;
    i |= b[1];
    return i;
}

//allgemeiner und mit Fehlerbehandlung:
template &lt;class T&gt;
T read_big_endian_int(const char * &amp;b, const char *end)
{
	T result = 0;
	const char * const end_of_int = (b + sizeof(result));
	if (end_of_int &gt; end)
	{
		throw std::runtime_error(&quot;Unexpected end of read buffer&quot;);
	}
	for (; b != end_of_int; ++b)
	{
		result &lt;&lt;= 8;
		result |= *b;
	}
    return result;
}

#include &lt;cstdint&gt;

//wird natürlich mit Typen bestimmter Größe verwendet
read_big_endian_int&lt;std::uint32_t&gt;(pos, end);
</code></pre>
<p>caster_caster schrieb:</p>
<blockquote>
<p>Das ganze läuft auf einem i7<br />
[...]<br />
Das hier passiert dabei an einer sehr performanceintensiven Stelle (das wird alles ~ 6 millionen mal gemacht), weshalb es möglichst schnell sein sollte.</p>
</blockquote>
<p>Ähh, 6 Millionen von diesen billigen Operationen macht so ein Prozessor im Schlaf.<br />
Deutlich teurer als das reine Zusammensetzen der <code>short</code> s ist bereits das Holen der Daten aus dem RAM in den Cache.<br />
Nochmal viel länger dauert das Lesen der Datei von einem Festspeicher.<br />
Der Teil, auf den du effektiv Einfluss hast, ist unbedeutend für die Geschwindigkeit.<br />
Viel wichtiger ist an der Stelle, dass das Programm korrekt arbeitet. Das ist mit einer portablen, übersichtlichen Umwandlung (siehe <code>read_big_endian_int</code> ) viel einfacher als mit Zeiger-Gefrickel.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2279624</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279624</guid><dc:creator><![CDATA[TyRoXx]]></dc:creator><pubDate>Wed, 12 Dec 2012 23:19:21 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Thu, 13 Dec 2012 07:09:59 GMT]]></title><description><![CDATA[<p>TyRoXx schrieb:</p>
<blockquote>
<pre><code class="language-cpp">//vernünftiger Name, const, das unnötige unsigned weg
short read_big_endian_short(const char *b)
</code></pre>
</blockquote>
<p>Unnötiges <code>unsigned</code> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /> <code>char</code> nimmst du, wenn du mit alphanumerischen Zeichen arbeitest... und das ist doch hier gar nicht der Fall.<br />
Aber ich werde nun zukünftig eh Werners Rat befolgen. <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/2279648</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279648</guid><dc:creator><![CDATA[out]]></dc:creator><pubDate>Thu, 13 Dec 2012 07:09:59 GMT</pubDate></item><item><title><![CDATA[Reply to Casten von Array um bestimmten Wert rauszulesen -&amp;gt; Byteorder tauschen on Thu, 13 Dec 2012 10:22:25 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/22298">@TyRoxx</a>. Ich habe mich in der Zahl geirrt. Es sind eher 144 Millionen mal, die dieses Teil pro Sekunde durchlaufen wird. Wobei auch bei 6 Millionen mal &quot;im Schlaf&quot; wohl nicht genug wäre. Im Schlaf heisst dann üblicherweise auch mindestens ne halbe ms (wenns nicht sowieso viel mehr sind) und so viel Zeit zu verschwenden nur weil die Daten ungünstig im Speicher liegen tut mir weh.</p>
<p>Ich mach das nun übrigens einfach mit inline Assembler:</p>
<p>__asm<br />
{<br />
mov eax,val<br />
bswap eax<br />
mov val,eax<br />
}</p>
<p>tada.</p>
<p>Damit ihr nicht gleich mit der Premature-Optimization Keule schwingt: Ich hab hier ein Codestück, das von ~250ms Laufzeit auf ~120ms Laufzeit zu drücken ist. Algorithmisch ist in dem Codestück nichts mehr zu machen, weshalb ich jetzt Code-mäßig einiges rausholen muss. Bis jetzt läufts noch ganz gut, die (neu implementierte) Funktion ist geschätzt 50% fertig und läuft in 40-60ms durch (die Zeitmessung mit high-performance-countern schwankt hier ziemlich).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2279681</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2279681</guid><dc:creator><![CDATA[caster_caster]]></dc:creator><pubDate>Thu, 13 Dec 2012 10:22:25 GMT</pubDate></item></channel></rss>