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

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

31

18.06.2014, 20:35

Also zumindest...

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
int main()
{
    std::ofstream F("T:\\TEST.txt", std::ios::binary);
    static const int SomeValue = 232392;
    F << SomeValue;
    if (F.bad())
        __debugbreak();
    return 0;
}

... funktioniert bei mir nicht? Also es landet die Zahl in 6 Buchstaben in der Datei.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

32

18.06.2014, 20:56

Ja, weil Du "<<" statt write verwendest. Das macht explizit eine Formatierung.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

33

18.06.2014, 21:02

Genau das hatte ich doch geschrieben... ?

Zitat von »Spieleprogrammierer«

Also das(Der operator >> wie in seinen Beispiel) sollte aber nicht funktionieren. [...] Für binäre Operationen bleiben doch nur "reinterpret_cast" + "write"/"read" Methoden in C++...

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

34

18.06.2014, 21:11

Mea Culpa. 13 Stunden Arbeit waren definitiv ein paar zu viel.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

35

18.06.2014, 22:58

Also falls Big Endian Systeme tatsächlich eine Rolle spielen würde ich dir dringend raten, Bytes nicht manuell je nach Architektur zu vertauschen. Da vertut man sich schnell (so wie z.B. Evrey) und man merkt es erst, wenn der Code tatsächlich auf Big Endian Systemen läuft. Schreib den Code lieber so, dass er nicht von der Endianness abhängt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
void WriteByte(std::ostream& out, uint8_t Byte)
{
    out.write((const char*)&Byte, 1);
}
void WriteInt(std::ostream& out, uint32_t Int)
{
    WriteByte(out, Int >> 0);
    WriteByte(out, Int >> 8);
    WriteByte(out, Int >> 16);
    WriteByte(out, Int >> 24);
}
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

36

19.06.2014, 00:24

Sorry, wenn das jetzt Frech klingt, aber: Funktioniert das auch? Gibt es später keine Probleme beim einlesen, wenn man die Bytes unabhängig von einander speichert?
Oder muss ich diese dann nur wieder Byte weise anreihen und der Rest klärt sich von selbst? Wenn das tatsächlich so einfach funktioniert, würde das ja echt einiges erleichtern. :)

Wenn ich schon dabei bin, ... (Ich hoffe keiner wird mich dafür erschlagen wollen :P):

Wenn man einen String abspeichern will, würde so etwas:

C-/C++-Quelltext

1
file.write(str.data(), str.size());

funktionieren, oder muss man tatsächlich jeden char des strings einzeln abspeichern, weil es sonst "verbunden" abgespeichert wird?

Ach ja, ehm... ich habe gerade gesehen das int32_t nichts anderes als ein typedef auf int ist.
Das muss ja dann im Umkehrschluss heißen, dass ein int auf jedem System immer 4 Byte groß ist, oder irre ich mich?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Jack« (19.06.2014, 00:29)


Tobiking

1x Rätselkönig

  • Private Nachricht senden

37

19.06.2014, 01:09

Ach ja, ehm... ich habe gerade gesehen das int32_t nichts anderes als ein typedef auf int ist.
Das muss ja dann im Umkehrschluss heißen, dass ein int auf jedem System immer 4 Byte groß ist, oder irre ich mich?

Du irrst dich. Der Typedef gehört zur Standardbibliothek, und diese ist für jedes System entsprechend implementiert. Dort steht unter Umständen also ein ganz anderer Typedef. Du schaust gerade nur in die Implementierung der Standardbibliothek für dein System.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

38

19.06.2014, 01:35

Zitat

Funktioniert das auch?

Ja

Zitat

Oder muss ich diese dann nur wieder Byte weise anreihen

Ja. Wenn du ganze Wörter einliest die aus mehreren Bytes bestehen, wäre deren Aufbau ja wieder undefiniert.

Zitat

Wenn das tatsächlich so einfach funktioniert, würde das ja echt einiges erleichtern.

Ja, es funktioniert so. Der einzige Nachteil ist eine geringere Effizienz. Wenn du damit leben kannst, kannst du es genauso gut so machen.

Wegen dem String: Also prinzipiell geht das natürlich. Das Problem an sich ist ja nicht unbedingt das mehrere Bytes "verbunden" sind, sondern nur, dass undefiniert ist, wie der Verbund genau aufgebaut ist. Bei Arrays sollte das aber definiert sein. Allerdings hoffe ich für dich, dass du für Strings bereits UTF-8 einsetzt, denn es gibt ja verschiedenste Codierungen wie Zeichen gespeichert werden können. Bei Wide-Char Strings wäre das speichern nämlich nicht so einfach. Dazu tragen 2 Dinge bei: 1. Wide-Chars bestehen ja wieder aus mehreren Bytes und sind Endian-abhänig. Es wäre also notwendig alle Zeichen wieder von Hand zurecht zu drehen und 2. ist nicht definiert wie groß Wide-Char ist und wie es die Zeichen enthält. Auf Windows wird dort UTF-16 eingesetzt, auf den meisten anderen Plattformen UTF-32. Nicht bloß deshalb sondern auch aus Gründen der Portabilität und technischen Gründen solltest du also konsequent UTF-8 einsetzen, sonst wird das nicht so einfach.

Wegen der Typdefinition... du irrst dich. ;) Auf deinem Compiler mag es vielleicht im Moment auf einen "int" definiert sein, aber nichts und niemand zwingt eine andere Plattform dazu, das selbe zu tun. Tatsächlich wären Typedefs in der Regel ziemlich sinnlos, wenn sie sich nicht je nach Präprozessordefinition oder Plattform ändern könnten. Wie du ja auch schon festgestellt hast, könnte man dann einfach den darunter liegenden Typ direkt verwenden und sich das sparen. Tatsächlich trifft es auf heutigen System fast immer zu, dass ein "int" auch 32 Bit groß ist. Aber es ist eben nichts garantiert. Und der Konsequenz und Sauberkeit wegen, würde ich deshalb auf die integrierten Typen verzichten. Bei anderen Typedefs wirst du aber auch leicht eine Änderung zwischen Plattformen betrachten können. Zum Beispiel "int64_t", "size_t" und andere. Und natürlich sind die auch intern irgendwie auf die integrierten Typen abgebildet, nur eben nicht immer auf den selben.

Evrey

Treue Seele

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

39

19.06.2014, 11:11

@Helmut: Wie gesagt, keine Garantie auf Richtigkeit. Nutze die C++ -Streams fast nur für formatierte Text-Ausgabe. Deine Lösung ist halt die, die Endianness der Datei festzulegen, in dem Fall Little Endian.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

40

19.06.2014, 16:25

So ich hab mein Problem endlich mal behoben, es lag an dem code array das aus chars, statt aus unsigned chars bestand.

Außerdem habe ich auch mal eine magic value an den Anfang jeder Snippet (Name meiner "Sprache") Binärdatei gehangen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
// add magic value
std::uint32_t magic = 's'|'n'<<8|'i'<<16|'p'<<24;
file.write(reinterpret_cast<char*>(&magic), sizeof(std::uint32_t));

// [...]

// check magic value
bool byteSwap = false;

if(code[0] != 's' || code[1] != 'n' || code[2] != 'i' || code[3] != 'p'){
    byteSwap = true;
}


Wann genau kann es jetzt zu Endian Problemen kommen?
Also wie liegen die Bytes dann vor, Evrey hatte ja als Prüfsumme "oxbc" genommen, wobei bei ihm nur die mittleren beiden Bytes vertauscht waren. Ist das immer so?

Werbeanzeige