<?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[Ein paar Fragen zu memcpy und versch. Datentypen]]></title><description><![CDATA[<p>Hallo!</p>
<p>Vielleicht mögen die Fragen ein wenig blöd klingen allerdings beschäftigt mich das jetzt schon ein paar Tage.</p>
<p><strong>[1]</strong><br />
Folgendes Szenario: Es liegt ein eigenes Dateiformat vor:</p>
<pre><code class="language-cpp">template&lt;class CharType&gt;
struct FILE_HEADER
{
    CharType  m_Signature[20];
    int       m_Value1;
    int       m_Value2;
    CharType  m_Data[100];
    size_t    m_DataLen;
};
</code></pre>
<p>Oben soll also beispielsweise ein Header für das Dateiformat gegeben sein.<br />
Ich speichere und lese ihn wie folgt aus einer Datei:</p>
<pre><code class="language-cpp">template &lt;class CharType&gt;
void Write(const CharType *pFileName)
{
    FILE_HEADER Hdr;
    std::ofstream file(pFileName);
    CharType *pOut = new CharType[sizeof(FILE_HEADER)];   

    // Header mit Daten füllen
    FillHeader(&amp;Hdr);

    // Struktur in Puffer kopieren
    memcpy(pOut, &amp;Hdr, sizeof(FILE_HEADER));

    // Speichern
    file.write(pOut, sizeof(FILE_HEADER));

    delete [] pOut;

    file.close();    
} 

template &lt;class CharType&gt;
void Reade(const CharType *pFileName, FILE_HEADER &amp;Hdr)
{
    std::ofstream file(pFileName);
    CharType *pIn = new CharType[sizeof(FILE_HEADER)];   

    // Lesen
    file.read(pIn, sizeof(FILE_HEADER));

    // Puffer in Struktur kopieren
    memcpy(&amp;Hdr, pIn, sizeof(FILE_HEADER));

    delete [] pIn;

    file.close();    
}
</code></pre>
<p>Kann hier mit dem memcpy irgendwas schiefgehen, also das nicht alle Daten der Struktur oder aus der gelesenen Datei erwischt werden? Ich meine keine Lese-/Schreibfehler.</p>
<p>Hier habe ich auch noch eine Frage zu &quot;#pragma pack&quot;. Bezieht sich auf MS Compiler. Ich verstehe aus der MSDN Beschreibung nicht ganz was #pragma pack bewirkt. Es nimmt Einfluss darauf wie die Daten im Speicher liegen. Was heißt das genau und müsste ich ich hier vor meine FILE_HEADER Struktur ein #pragma pack(1) und am Ende wieder ein #pragma pack() setzen?</p>
<p><strong>[2]</strong><br />
Es sollen meherer Strings inkl. ihrer Längen kopiert werden und in einen anderen String kopiert werden, welcher dann verschlüsselt wird und ebenfalls in die Datei geschrieben wird.</p>
<pre><code class="language-cpp">template&lt;class CharType&gt;
void SaveStrings(const std::basic_string&lt;CharType&gt; &amp;s1, const std::basic_string&lt;CharType&gt; &amp;s2, const std::basic_string&lt;CharType&gt; &amp;s3)
{
    CharType *pOut   = 0;
    size_t    OutLen = sizeof(size_t) * 3 + // 3 Längenangaben der Strings
                       s1.size() + s2.size() + s3.size();
    size_t    Pos    = 0;

    Chartype pOut = new CharType[OutLen];

    memcpy(&amp;s1.size(), pOut, sizeof(size_t));
    Pos += sizeof(size_t);

    memcpy(&amp;s2.size(), pOut + Pos, sizeof(size_t));
    Pos += sizeof(size_t);

    memcpy(&amp;s3.size(), pOut + Pos, sizeof(size_t));
    Pos += sizeof(size_t);

    memcpy(s1.c_str(), pOut + Pos, s1.size());
    Pos += s1.size();

    memcpy(s2.c_str(), pOut + Pos, s2.size());
    Pos += s2.size();

    memcpy(s3.c_str(), pOut + Pos, s3.size());

    // Verschlüsseln und Speichern

    delete [] pOut;
}
</code></pre>
<p>Das Laden des String erfolgt ähnlich. Auslesen, Entschlüsseln String kopieren:</p>
<pre><code class="language-cpp">size_t size = 0;

    // Längen auslesen
    memcpy(pIn, &amp;size, sizeof(size_t));
</code></pre>
<p>Mit memcpy sollte auch hier doch nichts schiefgehen, da doch nur die Bytes kopiert werden, oder müsste man die Längenangaben extra per Bitoperationen in einen CharType wandeln wie hier zu sehen</p>
<pre><code class="language-cpp">void ulong_to_uchar (unsigned char pBuf[4], const unsigned long &amp;val)
{
    pBuf[0] = static_cast&lt;unsigned char&gt;( ( vVal  &gt;&gt; 24 )  &amp; 0xff );
    pBuf[1] = static_cast&lt;unsigned char&gt;( ( val  &gt;&gt; 16 )  &amp; 0xff );
    pBuf[2] = static_cast&lt;unsigned char&gt;( ( val  &gt;&gt;  8 )  &amp; 0xff );
    pBuf[3] = static_cast&lt;unsigned char&gt;(   val           &amp; 0xff );
}
</code></pre>
<p>und dann diesen char ein den String kopieren? An sich müsste es doch memcpy egal sein was für Daten es kopiert. Hauptsache keine Pufferüberläufe.</p>
<p>Hoffe es ist halbwegs zu verstehen was ich wissen möchte.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/185615/ein-paar-fragen-zu-memcpy-und-versch-datentypen</link><generator>RSS for Node</generator><lastBuildDate>Thu, 24 Sep 2026 05:22:03 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/185615.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 29 Jun 2007 08:08:01 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 08:08:01 GMT]]></title><description><![CDATA[<p>Hallo!</p>
<p>Vielleicht mögen die Fragen ein wenig blöd klingen allerdings beschäftigt mich das jetzt schon ein paar Tage.</p>
<p><strong>[1]</strong><br />
Folgendes Szenario: Es liegt ein eigenes Dateiformat vor:</p>
<pre><code class="language-cpp">template&lt;class CharType&gt;
struct FILE_HEADER
{
    CharType  m_Signature[20];
    int       m_Value1;
    int       m_Value2;
    CharType  m_Data[100];
    size_t    m_DataLen;
};
</code></pre>
<p>Oben soll also beispielsweise ein Header für das Dateiformat gegeben sein.<br />
Ich speichere und lese ihn wie folgt aus einer Datei:</p>
<pre><code class="language-cpp">template &lt;class CharType&gt;
void Write(const CharType *pFileName)
{
    FILE_HEADER Hdr;
    std::ofstream file(pFileName);
    CharType *pOut = new CharType[sizeof(FILE_HEADER)];   

    // Header mit Daten füllen
    FillHeader(&amp;Hdr);

    // Struktur in Puffer kopieren
    memcpy(pOut, &amp;Hdr, sizeof(FILE_HEADER));

    // Speichern
    file.write(pOut, sizeof(FILE_HEADER));

    delete [] pOut;

    file.close();    
} 

template &lt;class CharType&gt;
void Reade(const CharType *pFileName, FILE_HEADER &amp;Hdr)
{
    std::ofstream file(pFileName);
    CharType *pIn = new CharType[sizeof(FILE_HEADER)];   

    // Lesen
    file.read(pIn, sizeof(FILE_HEADER));

    // Puffer in Struktur kopieren
    memcpy(&amp;Hdr, pIn, sizeof(FILE_HEADER));

    delete [] pIn;

    file.close();    
}
</code></pre>
<p>Kann hier mit dem memcpy irgendwas schiefgehen, also das nicht alle Daten der Struktur oder aus der gelesenen Datei erwischt werden? Ich meine keine Lese-/Schreibfehler.</p>
<p>Hier habe ich auch noch eine Frage zu &quot;#pragma pack&quot;. Bezieht sich auf MS Compiler. Ich verstehe aus der MSDN Beschreibung nicht ganz was #pragma pack bewirkt. Es nimmt Einfluss darauf wie die Daten im Speicher liegen. Was heißt das genau und müsste ich ich hier vor meine FILE_HEADER Struktur ein #pragma pack(1) und am Ende wieder ein #pragma pack() setzen?</p>
<p><strong>[2]</strong><br />
Es sollen meherer Strings inkl. ihrer Längen kopiert werden und in einen anderen String kopiert werden, welcher dann verschlüsselt wird und ebenfalls in die Datei geschrieben wird.</p>
<pre><code class="language-cpp">template&lt;class CharType&gt;
void SaveStrings(const std::basic_string&lt;CharType&gt; &amp;s1, const std::basic_string&lt;CharType&gt; &amp;s2, const std::basic_string&lt;CharType&gt; &amp;s3)
{
    CharType *pOut   = 0;
    size_t    OutLen = sizeof(size_t) * 3 + // 3 Längenangaben der Strings
                       s1.size() + s2.size() + s3.size();
    size_t    Pos    = 0;

    Chartype pOut = new CharType[OutLen];

    memcpy(&amp;s1.size(), pOut, sizeof(size_t));
    Pos += sizeof(size_t);

    memcpy(&amp;s2.size(), pOut + Pos, sizeof(size_t));
    Pos += sizeof(size_t);

    memcpy(&amp;s3.size(), pOut + Pos, sizeof(size_t));
    Pos += sizeof(size_t);

    memcpy(s1.c_str(), pOut + Pos, s1.size());
    Pos += s1.size();

    memcpy(s2.c_str(), pOut + Pos, s2.size());
    Pos += s2.size();

    memcpy(s3.c_str(), pOut + Pos, s3.size());

    // Verschlüsseln und Speichern

    delete [] pOut;
}
</code></pre>
<p>Das Laden des String erfolgt ähnlich. Auslesen, Entschlüsseln String kopieren:</p>
<pre><code class="language-cpp">size_t size = 0;

    // Längen auslesen
    memcpy(pIn, &amp;size, sizeof(size_t));
</code></pre>
<p>Mit memcpy sollte auch hier doch nichts schiefgehen, da doch nur die Bytes kopiert werden, oder müsste man die Längenangaben extra per Bitoperationen in einen CharType wandeln wie hier zu sehen</p>
<pre><code class="language-cpp">void ulong_to_uchar (unsigned char pBuf[4], const unsigned long &amp;val)
{
    pBuf[0] = static_cast&lt;unsigned char&gt;( ( vVal  &gt;&gt; 24 )  &amp; 0xff );
    pBuf[1] = static_cast&lt;unsigned char&gt;( ( val  &gt;&gt; 16 )  &amp; 0xff );
    pBuf[2] = static_cast&lt;unsigned char&gt;( ( val  &gt;&gt;  8 )  &amp; 0xff );
    pBuf[3] = static_cast&lt;unsigned char&gt;(   val           &amp; 0xff );
}
</code></pre>
<p>und dann diesen char ein den String kopieren? An sich müsste es doch memcpy egal sein was für Daten es kopiert. Hauptsache keine Pufferüberläufe.</p>
<p>Hoffe es ist halbwegs zu verstehen was ich wissen möchte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314695</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314695</guid><dc:creator><![CDATA[HaJo.]]></dc:creator><pubDate>Fri, 29 Jun 2007 08:08:01 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 08:14:40 GMT]]></title><description><![CDATA[<p>Teilantworten:<br />
Also bei Deiner Datenstruktur sollte pack(1) keinen Einfluss habe, da Deine Addressen alle durch 4 (defaultwert) teilbar sind.<br />
Generell muss pack beim schreiben und lesen einfach gleich sein.</p>
<p>Deine Version von ulong_to_uchar ist plattform bzw little-big-endian unabhängig also &quot;besser&quot; als memcopy aber langsamer(falls du es sehrsehrsehr oft aufrufst)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314701</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314701</guid><dc:creator><![CDATA[templäd]]></dc:creator><pubDate>Fri, 29 Jun 2007 08:14:40 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 08:35:43 GMT]]></title><description><![CDATA[<p>@1: memcpy() kopiert byteweise den kompletten Speicherbereich - da du keine &quot;externen&quot; Daten verwendest, ist das hier völlig ausreichend (aber unnötig - du kannst auch read()/write() direkt auf deine FILE_HEADER loslassen).</p>
<p>@1b: &quot;#pragma pack()&quot; gibt an, wie die Strukturelemente im Speicher ausgerichtet werden. Je nach Einstellung (und Größe der Member) können noch Füll-Bytes dazwischengeschoben werden, um die Adressen zu korrigieren. Das wird nur dann problematisch, wenn du die Daten zwischen verschiedenen Systemen austauschen willst.</p>
<p>@2: Wenn alle Teile des Programms vom selben Compiler stammen, passt auch die Bitlage deiner Zahlenwerte zusammen. Wenn du auf diesem Weg Daten zwischen verschiedenen Systemen austauschen willst, ist die Anpassung über Bit-Operationen sicherer (btw, das gilt auch für die int-Anteile aus Teil [1]).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314722</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314722</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Fri, 29 Jun 2007 08:35:43 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 10:23:10 GMT]]></title><description><![CDATA[<p>templäd schrieb:</p>
<blockquote>
<p>Teilantworten:<br />
Also bei Deiner Datenstruktur sollte pack(1) keinen Einfluss habe, da Deine Addressen alle durch 4 (defaultwert) teilbar sind.<br />
Generell muss pack beim schreiben und lesen einfach gleich sein.</p>
</blockquote>
<p>Also das alles durch 4 teilbar ist, ist glaube ich Zufall. Würde folgende abgeänderte Struktur an Funktionalität etwas ändern?</p>
<pre><code class="language-cpp">template&lt;class CharType&gt;
struct FILE_HEADER
{
    CharType  m_Signature[23]; // vorher 20
    int       m_Value1;
    int       m_Value2;
    CharType  m_Data[111]; // vorher 100
    size_t    m_DataLen;
};
</code></pre>
<p>templäd schrieb:</p>
<blockquote>
<p>Deine Version von ulong_to_uchar ist plattform bzw little-big-endian unabhängig also &quot;besser&quot; als memcopy aber langsamer(falls du es sehrsehrsehr oft aufrufst)</p>
</blockquote>
<p>Also entnehme ich darus das es in meinem Fall egal ist. Die Software soll nur unter Windows laufen auf Intel- bzw. IBM kompatiblen Systemen.</p>
<p>CStoll schrieb:</p>
<blockquote>
<p>@1: memcpy() kopiert byteweise den kompletten Speicherbereich - da du keine &quot;externen&quot; Daten verwendest, ist das hier völlig ausreichend (aber unnötig - du kannst auch read()/write() direkt auf deine FILE_HEADER loslassen).</p>
</blockquote>
<p>Müsste dann nur in CharType casten also</p>
<pre><code class="language-cpp">std::basic_fstream&lt;CharType&gt; file(&quot;Dateiname&quot;);

file.write(reinterpret_cast&lt;CharType*&gt;(&amp;Header), sizeof(FILE_HEADER&lt;CharType&gt;));
</code></pre>
<p>Wäre um einiges performater, da ich eine Speicheranforderung weglassen kann.</p>
<p>CStoll schrieb:</p>
<blockquote>
<p>@1b: &quot;#pragma pack()&quot; gibt an, wie die Strukturelemente im Speicher ausgerichtet werden. Je nach Einstellung (und Größe der Member) können noch Füll-Bytes dazwischengeschoben werden, um die Adressen zu korrigieren. Das wird nur dann problematisch, wenn du die Daten zwischen verschiedenen Systemen austauschen willst.</p>
</blockquote>
<p>Wie oben erwähnt. Die Software soll nur unter Windowssystemen laufen. Hättest du vielleicht ein Beispiel wo #pragma pack(xyz) genutzt werden müsste?</p>
<p>CStoll schrieb:</p>
<blockquote>
<p>@2: Wenn alle Teile des Programms vom selben Compiler stammen, passt auch die Bitlage deiner Zahlenwerte zusammen. Wenn du auf diesem Weg Daten zwischen verschiedenen Systemen austauschen willst, ist die Anpassung über Bit-Operationen sicherer (btw, das gilt auch für die int-Anteile aus Teil [1]).</p>
</blockquote>
<p>Also kein Problem solange es unter Windowssystemen läuft. Wenn es jetzt aber z.B. unter einem PowerPC wo Windows in einer VM läuft, würde es schiefgehen, richtig?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314821</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314821</guid><dc:creator><![CDATA[HaJo.]]></dc:creator><pubDate>Fri, 29 Jun 2007 10:23:10 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 10:29:48 GMT]]></title><description><![CDATA[<p>HaJo. schrieb:</p>
<blockquote>
<p>Also kein Problem solange es unter Windowssystemen läuft. Wenn es jetzt aber z.B. unter einem PowerPC wo Windows in einer VM läuft, würde es schiefgehen, richtig?</p>
</blockquote>
<p>ne VM sollte tunlichst das windows bit-ordering emulieren, sonst wärs keine anständige VM. probleme bekommst dann, wenn dein programm nativ auf anderen system laufen soll.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314832</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314832</guid><dc:creator><![CDATA[thordk]]></dc:creator><pubDate>Fri, 29 Jun 2007 10:29:48 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 10:39:26 GMT]]></title><description><![CDATA[<p>thordk schrieb:</p>
<blockquote>
<p>ne VM sollte tunlichst das windows bit-ordering emulieren, sonst wärs keine anständige VM. probleme bekommst dann, wenn dein programm nativ auf anderen system laufen soll.</p>
</blockquote>
<p>Stimmt. Im Nachhinein wohl schwachsinn. Danke.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314848</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314848</guid><dc:creator><![CDATA[HaJo.]]></dc:creator><pubDate>Fri, 29 Jun 2007 10:39:26 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 10:43:31 GMT]]></title><description><![CDATA[<p>HaJo. schrieb:</p>
<blockquote>
<p>CStoll schrieb:</p>
<blockquote>
<p>@1: memcpy() kopiert byteweise den kompletten Speicherbereich - da du keine &quot;externen&quot; Daten verwendest, ist das hier völlig ausreichend (aber unnötig - du kannst auch read()/write() direkt auf deine FILE_HEADER loslassen).</p>
</blockquote>
<p>Müsste dann nur in CharType casten also</p>
<pre><code class="language-cpp">std::basic_fstream&lt;CharType&gt; file(&quot;Dateiname&quot;);

file.write(reinterpret_cast&lt;CharType*&gt;(&amp;Header), sizeof(FILE_HEADER&lt;CharType&gt;));
</code></pre>
<p>Wäre um einiges performater, da ich eine Speicheranforderung weglassen kann.</p>
</blockquote>
<p>Ja, genau so sollte es funktionieren (abgesehen von der Tatsache, daß FILE_HEADER kein Template ist ;)).</p>
<blockquote>
<p>CStoll schrieb:</p>
<blockquote>
<p>@1b: &quot;#pragma pack()&quot; gibt an, wie die Strukturelemente im Speicher ausgerichtet werden. Je nach Einstellung (und Größe der Member) können noch Füll-Bytes dazwischengeschoben werden, um die Adressen zu korrigieren. Das wird nur dann problematisch, wenn du die Daten zwischen verschiedenen Systemen austauschen willst.</p>
</blockquote>
<p>Wie oben erwähnt. Die Software soll nur unter Windowssystemen laufen. Hättest du vielleicht ein Beispiel wo #pragma pack(xyz) genutzt werden müsste?</p>
</blockquote>
<p>Auf Anhieb nicht. Solche Anpassungen brauchst du vor allem, wenn du ein bestimmtes Speicher-Layout erzwingen willst. Bei deiner geänderten Struktur könnten z.B. nach den beiden char-Arrays padding-Bytes eingefügt werden, die (a) eventuell unnötigen Speicherplatz verbrauchen und (b) das Layout durcheinanderwürfeln können.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314851</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314851</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Fri, 29 Jun 2007 10:43:31 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 10:52:49 GMT]]></title><description><![CDATA[<p>CStoll schrieb:</p>
<blockquote>
<p>Ja, genau so sollte es funktionieren (abgesehen von der Tatsache, daß FILE_HEADER kein Template ist ;)).</p>
</blockquote>
<p>Doch, FILE_HEADER ist doch ein Template. <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>
<pre><code class="language-cpp">template&lt;class CharType&gt;struct FILE_HEADER { /* ... */ };
</code></pre>
<p>CStoll schrieb:</p>
<blockquote>
<p>Auf Anhieb nicht. Solche Anpassungen brauchst du vor allem, wenn du ein bestimmtes Speicher-Layout erzwingen willst. Bei deiner geänderten Struktur könnten z.B. nach den beiden char-Arrays padding-Bytes eingefügt werden, die (a) eventuell unnötigen Speicherplatz verbrauchen und (b) das Layout durcheinanderwürfeln können.</p>
</blockquote>
<p>Schade. <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="🙂"
    /> Falls dir noch mal eines über den Weg läuft, wäre ich dran interessiert. Also sollte es auch noch mit der geänderten Sruktur, wo nicht mehr alle Memeber durch 4 teilbar sind klappen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314861</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314861</guid><dc:creator><![CDATA[HaJo.]]></dc:creator><pubDate>Fri, 29 Jun 2007 10:52:49 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 11:00:39 GMT]]></title><description><![CDATA[<p>HaJo. schrieb:</p>
<blockquote>
<p>CStoll schrieb:</p>
<blockquote>
<p>Ja, genau so sollte es funktionieren (abgesehen von der Tatsache, daß FILE_HEADER kein Template ist ;)).</p>
</blockquote>
<p>Doch, FILE_HEADER ist doch ein Template. <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>
<pre><code class="language-cpp">template&lt;class CharType&gt;struct FILE_HEADER { /* ... */ };
</code></pre>
</blockquote>
<p>Ups, stimmt. Das hatte ich übersehen.</p>
<blockquote>
<p>CStoll schrieb:</p>
<blockquote>
<p>Auf Anhieb nicht. Solche Anpassungen brauchst du vor allem, wenn du ein bestimmtes Speicher-Layout erzwingen willst. Bei deiner geänderten Struktur könnten z.B. nach den beiden char-Arrays padding-Bytes eingefügt werden, die (a) eventuell unnötigen Speicherplatz verbrauchen und (b) das Layout durcheinanderwürfeln können.</p>
</blockquote>
<p>Schade. <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="🙂"
    /> Falls dir noch mal eines über den Weg läuft, wäre ich dran interessiert. Also sollte es auch noch mit der geänderten Sruktur, wo nicht mehr alle Memeber durch 4 teilbar sind klappen.</p>
</blockquote>
<p>Theoretisch ja, praktisch müsstest du mal sehen, ob dich die Padding-Bytes im Ernstfall stören.</p>
<p>PS: Laut meiner MSDN ist der Defaultwert für's Padding bei 8, also hast du auch in der Originalversion möglicherweise schon Lücken im Objekt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314864</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314864</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Fri, 29 Jun 2007 11:00:39 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 11:22:11 GMT]]></title><description><![CDATA[<p>CStoll schrieb:</p>
<blockquote>
<p>Theoretisch ja, praktisch müsstest du mal sehen, ob dich die Padding-Bytes im Ernstfall stören.</p>
</blockquote>
<p>Also. Ich habe mal Testweise die Struktur mit Zufallswerten gefüllt in einer Schleife in die Datei schreiben lassen und wieder auslesen lassen. Dann mit memcmp die Bytes verglichen und es haut alles hin. Das ist die Struktur</p>
<pre><code class="language-cpp">template&lt;class CharType&gt;
    struct MAIN_HEADER
    {
        CharType             m_pSignature[7];
        short                m_MajorVersion;
        short                m_MinorVersion;
        EncryptionAlgorithm  m_EncryptionAlgorithm;
        CharType             m_pSalt[32];
        int                  m_Counter;
        CharType             m_pReserved[54];
    };
</code></pre>
<p>Die &quot;echte&quot; Größe der Struktur ist 105 Bytes. Ohne #pragma pack Angaben - Standardwert 8 - ist die Struktur allerdings 108 Bytes groß. Also wird etwas aufgefüllt. Das mit dem Padding verstehe ich nicht ganz in der MSDN. Wozu dient das?<br />
Es läuft in meinem Test auch alles mit #pragma pack(1). Hier hat die Struktur dann ihre Originalgröße von 105 Bytes.</p>
<p>Eine Sache verunsichert mich hier allerdings:</p>
<p>MSDN schrieb:</p>
<blockquote>
<p>Note that if you change the alignment of a structure, the structure will not use as much space in memory, but you may see a decrease in performance or even get a hardware-generated exception for unaligned access. It is possible to modify this exception behavior with SetErrorMode.</p>
</blockquote>
<p>Ja, habe ich denn jetzt ein Performanzverlust bei #pragma pack(1)?</p>
<p>CStoll schrieb:</p>
<blockquote>
<p>PS: Laut <strong>meiner</strong> MSDN ist der Defaultwert für's Padding bei 8, also hast du auch in der Originalversion möglicherweise schon Lücken im Objekt.</p>
</blockquote>
<p>Klingt nett. Ich habe auch eine. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314882</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314882</guid><dc:creator><![CDATA[HaJo.]]></dc:creator><pubDate>Fri, 29 Jun 2007 11:22:11 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 11:34:35 GMT]]></title><description><![CDATA[<p>OK, dann etwas ausführlicher: Das Padding dient dazu, die Position einzelner Member an &quot;gutartigen&quot; Speicheradressen auszurichten. Nehmen wir also eine etwas einfachere Struktur:</p>
<pre><code class="language-cpp">struct test
{
  char c;
  int i;
};
</code></pre>
<p>Die Verbindung zwischen Prozessor und Speicher kann heute meist 4 Byte auf einmal übertragen, also ist es günstig, wenn der int-Wert an einer Adresse steht, die durch 4 teilbar ist. da der char nur 1 Byte benötigt, wird das erreicht, indem noch 3 Füllbytes dazwischengeschoben werden (welchen Wert die haben, ist nicht festgelegt<sup>*</sup>) - damit hat die gesamte Struktur eine Größe von 8 Byte (c(1)+3+4(i)).</p>
<p>Wenn du das Padding ausschaltest, werden alle Elemente lückenlos hintereinander untergebracht, dadurch reduziert sich die Größe auf 5. Allerdings liegt der int jetzt nicht mehr geeignet im Speicher, um auf einen Schlag ausgelesen zu werden - also muß das Programm für einen Zugriff erst zwei 4-Byte-Blöcke lesen und daraus den int-Wert zusammenbauen (und in der anderen Richtung ihn wieder zerlegen und in Einzelteilen zurückschreiben).</p>
<p><sup>*</sup> das bedeutet auch, daß du mitunter falsche Antworten erhältst, wenn du eine Struktur elementweise kopierst und dann per memcmp() vergleichst:</p>
<pre><code class="language-cpp">test t1 = {'a',4711},t2;
t2.c=t1.c;t2.i=t1.i;
cout&lt;&lt;(memcmp(t1,t2)==0)?&quot;gleich&quot;:&quot;verschieden&quot;;//was hier ausgegeben wird, hängt von den willkürlichen Werten der Padding-Bytes ab
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1314889</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314889</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Fri, 29 Jun 2007 11:34:35 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 11:53:25 GMT]]></title><description><![CDATA[<p>CStoll schrieb:</p>
<blockquote>
<p>OK, dann etwas ausführlicher: Das Padding dient dazu, die Position einzelner Member an &quot;gutartigen&quot; Speicheradressen auszurichten. Nehmen wir also eine etwas einfachere Struktur:</p>
<pre><code class="language-cpp">struct test
{
  char c;
  int i;
};
</code></pre>
<p>Die Verbindung zwischen Prozessor und Speicher kann heute meist 4 Byte auf einmal übertragen, also ist es günstig, wenn der int-Wert an einer Adresse steht, die durch 4 teilbar ist. da der char nur 1 Byte benötigt, wird das erreicht, indem noch 3 Füllbytes dazwischengeschoben werden (welchen Wert die haben, ist nicht festgelegt<sup>*</sup>) - damit hat die gesamte Struktur eine Größe von 8 Byte (c(1)+3+4(i)).</p>
<p>Wenn du das Padding ausschaltest, werden alle Elemente lückenlos hintereinander untergebracht, dadurch reduziert sich die Größe auf 5. Allerdings liegt der int jetzt nicht mehr geeignet im Speicher, um auf einen Schlag ausgelesen zu werden - also muß das Programm für einen Zugriff erst zwei 4-Byte-Blöcke lesen und daraus den int-Wert zusammenbauen (und in der anderen Richtung ihn wieder zerlegen und in Einzelteilen zurückschreiben).</p>
</blockquote>
<p>Wunderbar. Herzlichen Dank.</p>
<p>CStoll schrieb:</p>
<blockquote>
<p><sup>*</sup> das bedeutet auch, daß du mitunter falsche Antworten erhältst, wenn du eine Struktur elementweise kopierst und dann per memcmp() vergleichst:</p>
<pre><code class="language-cpp">test t1 = {'a',4711},t2;
t2.c=t1.c;t2.i=t1.i;
cout&lt;&lt;(memcmp(t1,t2)==0)?&quot;gleich&quot;:&quot;verschieden&quot;;//was hier ausgegeben wird, hängt von den willkürlichen Werten der Padding-Bytes ab
</code></pre>
</blockquote>
<p>Das heißt ich könnte mit meinen efrigen memcmp Vergleichen bei allen zig Testdurchläufen immer Glück gehabt haben und sollte lieber jeden Member einzeln vergleichen.</p>
<p>P.S.: Vor jedem Schreiben eines Header wird dieser intialisiert mit</p>
<pre><code class="language-cpp">memset(&amp;Header, 0x00, sizeof(MAIN_HEADER))
</code></pre>
<p>. Das erwischt doch auch die Paddingbytes, sodass memcmp wiederum nicht glücklich verlief sondern &quot;korrekt&quot;, oder?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314912</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314912</guid><dc:creator><![CDATA[HaJo.]]></dc:creator><pubDate>Fri, 29 Jun 2007 11:53:25 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 12:07:41 GMT]]></title><description><![CDATA[<p>Ja, memset() erwischt auch die Padding-Bytes.</p>
<p>(und bei deinem Ansatz oben (Daten schreiben, wieder einlesen und dann vergleichen) kommt auch aus Prinzip das richtige Ergebnis heraus, weil read() und write() ebenfalls alles ohne Rücksicht auf die interne Struktur lesen bzw. schreiben)</p>
<p>PS: Problematisch wird es, wenn du zwischen schreiben und lesen das Layout der Struktur geändert hast, d.h. wenn du z.B. einen Header schreibst, dann im Programm die Padding-Einstellungen änderst und mit der neuen Version diesen Header wieder auszulesen versuchst - dabei stimmen die Daten immer noch auf Byte-Ebene überein, aber die einzelnen Bytes gehören nicht mehr zu den selben Membern. Zum Beispiel bei meiner obigen test-Struktur:</p>
<pre><code class="language-cpp">//Lauf 1 mit Standard-Padding:
test t = {'a',4711};
file.write((char*)&amp;t,sizeof(test);
//Ergebnis: 61 xx xx xx 00 00 12 67

//Lauf 2 compiliert mit #pragma pack(1)
test t;
file.read((char*)&amp;t,sizeof(test);
//Ergebnis: 61 xx xx xx 00
//in t.i kann jetzt alles mögliche drin stehen, aber bestimmt nicht 4711
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1314925</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314925</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Fri, 29 Jun 2007 12:07:41 GMT</pubDate></item><item><title><![CDATA[Reply to Ein paar Fragen zu memcpy und versch. Datentypen on Fri, 29 Jun 2007 13:12:10 GMT]]></title><description><![CDATA[<p>CStoll schrieb:</p>
<blockquote>
<p>PS: Problematisch wird es, wenn du zwischen schreiben und lesen das Layout der Struktur geändert hast, d.h. wenn du z.B. einen Header schreibst, dann im Programm die Padding-Einstellungen änderst und mit der neuen Version diesen Header wieder auszulesen versuchst - dabei stimmen die Daten immer noch auf Byte-Ebene überein, aber die einzelnen Bytes gehören nicht mehr zu den selben Membern. Zum Beispiel bei meiner obigen test-Struktur:</p>
<pre><code class="language-cpp">//Lauf 1 mit Standard-Padding:
test t = {'a',4711};
file.write((char*)&amp;t,sizeof(test);
//Ergebnis: 61 xx xx xx 00 00 12 67

//Lauf 2 compiliert mit #pragma pack(1)
test t;
file.read((char*)&amp;t,sizeof(test);
//Ergebnis: 61 xx xx xx 00
//in t.i kann jetzt alles mögliche drin stehen, aber bestimmt nicht 4711
</code></pre>
</blockquote>
<p>Das sollte nicht passieren. Werde es einfach ohne eine #pragma pack Anweisung machen, da sie ja hier nicht nötig ist. Vielen Dank auch.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1314980</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1314980</guid><dc:creator><![CDATA[HaJo.]]></dc:creator><pubDate>Fri, 29 Jun 2007 13:12:10 GMT</pubDate></item></channel></rss>