Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

14.11.2015, 23:39

std::memcpy Verhalten auf verschiedenen Betriebssystemen

Guten Abend,
ich beschäftige mich jetzt endlich mal tatsächlich ein wenig tiefgründiger mit Netzwerkprogrammierung, hurra!

Ich arbeite mit Qt 5.3 und Visual Studio 2013, das nur mal als Hintergrundinfo.
In Qt gibt es so genannte QByteArrays was in etwa std::vector<char> entspricht. Diesen möchte ich mit entsprechenden Header Daten füllen.
Eine Zeichenkette um zu zeigen, dass das hier das Paket beginnt und danach 4 Bytes mit der danach folgenden Länge des Pakets.
Die Zeichenkette und sonstiges da sauber rein zu bekommen ist nicht das Problem, kniffliger wird es dann aber einen uint32_t in 4 chars aufzuteilen. Das habe ich jetzt mit einem std::memcpy gelöst. Funktioniert soweit auch wunderbar nur würde mich interessieren, ob es da Unterschiede von OS zu OS gibt, in welcher Reihenfolge die Bits im Array landen. Weiß da jemand genaueres, oder bin ich hier einfach zu Paranoid?
Es ist für mich bisher noch nicht ganz klar, auf welchem OS ich den Server laufen lassen möchte, der Client soll da möglichst portabel bleiben, deswegen ist es sehr wahrscheinlich, dass ich mal zu einem solchen Fall komme ;)

mfg

CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

2

14.11.2015, 23:49

Wenn du sowas wie Little- und Big-Endian meinst, dann kann dein Programm das rausfinden. Ich gebe mal das Stichwort "Byte-Reihenfole" (engl. Endianess). Hier kannst du vielleicht mehr darüber herausfinden.

Ich hoffe, ich konnte helfen und habe das richtige Thema getroffen! ;)
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

14.11.2015, 23:50

Das habe ich jetzt mit einem std::memcpy gelöst. Funktioniert soweit auch wunderbar nur würde mich interessieren, ob es da Unterschiede von OS zu OS gibt, in welcher Reihenfolge die Bits im Array landen. Weiß da jemand genaueres, oder bin ich hier einfach zu Paranoid?

Du bist in dem Fall nicht Paranoid, dein Stichwort lautet Endianness ;)

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

4

14.11.2015, 23:51

Also memcpy ändert an den Daten überhaupts.
Die Daten werden einfach Byte für Byte, Bit für Bit kopiert. Der Ausgabebuffer enthält dann exakt die selbe Bytesequenz wie die Eingabe.

Es gibt allerdings Unterschiede darin, welche Zahlen die immer selben Bytefolgen in einem Integer repräsentieren. Heutzutage besonders die Sache mit dem Endian. Kurz auf das Wichtigste zusammengefasst: Auf einige tendentiell seltener werdenden Plattformen, die mit Big Endian arbeiten, werden die Bytes in genau vertauschter Reihenfolge gespeichert. Falls man sich auf einer solchen Architektur befindet, muss man die Bytes beim Schreiben oder Lesen vertauschen. Man kann theoretisch auch mit Endian unabhänigen Code arbeiten.

5

14.11.2015, 23:53

Ok, wie löse ich dass dann möglichst Endian unabhängig?

EDIT: Auch gerne irgend eine mighty magic boost Funktion. ;)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

14.11.2015, 23:54

Das hängt stark davon ab, was du mit deinen 4 Byte genau anstellen willst... ;)

7

14.11.2015, 23:55

Das hängt stark davon ab, was du mit deinen 4 Byte genau anstellen willst... ;)

Wie bereits gesagt, ist da drin die Anzahl der nachfolgenden Bytes, die zum Paket gehören gespeichert

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

8

14.11.2015, 23:58

Zum Beispiel so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
uint32_t ConvFromLittleEndian(char const* MyByteBuffer)
{
    return static_cast<uint32_t>(MyByteBuffer[0]) |
        (static_cast<uint32_t>(MyByteBuffer[1]) << 8) |
        (static_cast<uint32_t>(MyByteBuffer[2]) << 16) |
        (static_cast<uint32_t>(MyByteBuffer[3]) << 24);
}
/*
//Für den Fall dass das Protokol BigEndian verwendet...
uint32_t ConvFromBigEndian(char const* MyByteBuffer)
{
    return static_cast<uint32_t>(MyByteBuffer[3]) |
        (static_cast<uint32_t>(MyByteBuffer[2]) << 8) |
        (static_cast<uint32_t>(MyByteBuffer[1]) << 16) |
        (static_cast<uint32_t>(MyByteBuffer[0]) << 24);
}*/

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

15.11.2015, 00:00

Das hängt stark davon ab, was du mit deinen 4 Byte genau anstellen willst... ;)

Wie bereits gesagt, ist da drin die Anzahl der nachfolgenden Bytes, die zum Paket gehören gespeichert

In dem Fall wohl am einfachsten die Länge immer in Network Byte Order übertragen und konvertieren, Stichwort: htonl()/ntohl(). Beachte allerdings, dass Endianness auch beim Inhalt deines Bytearrays eine Rolle spielen wird, sofern die Bytes nicht wirklich einfach nur als Array von Bytes verarbeitet werden oder auf sonst eine Art für korrektes Layout gesorgt wird...

10

15.11.2015, 00:03

Zum Beispiel so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
uint32_t ConvFromLittleEndian(char const* MyByteBuffer)
{
    return static_cast<uint32_t>(MyByteBuffer[0]) |
        (static_cast<uint32_t>(MyByteBuffer[1]) << 8) |
        (static_cast<uint32_t>(MyByteBuffer[2]) << 16) |
        (static_cast<uint32_t>(MyByteBuffer[3]) << 24);
}
/*
//Für den Fall dass das Protokol BigEndian verwendet...
uint32_t ConvFromBigEndian(char const* MyByteBuffer)
{
    return static_cast<uint32_t>(MyByteBuffer[3]) |
        (static_cast<uint32_t>(MyByteBuffer[2]) << 8) |
        (static_cast<uint32_t>(MyByteBuffer[1]) << 16) |
        (static_cast<uint32_t>(MyByteBuffer[0]) << 24);
}*/

Ja, ist ja vom Prinzip her das gleiche, wie das memcpy. Beim Big-Endian muss ich dann lediglich den vector reversen. Ich muss also praktisch bestimmen, welchen Endian Typ mein OS benutzt, und dementsprechend handeln.
Danke für die Antworten ;)

Werbeanzeige