Portabilität size_t
-
knivil schrieb:
Und doch es gibt einen Weg, den habe ich gezeigt.
...
Falls std::size_t weniger als 4 Bytes beim Kompilieren hat, wird die Kompilation abbrechen.Tja und dann?
Dann hast du die Sicherheit, dass du nicht ein Programm kompiliert hast, welches undefiniertes Verhalten auslöst. Es ist eine Sicherung mehr nicht. Da aber die verbreitesten und meisten Plattformen wohl
std::size_tmit 4 oder mehr Bytes versehen werden, wird der Code meistens kompilieren.Ansonsten kann man eben auch Boost verwenden. Die vereinen alle nicht portablen Erweiterungen und bieten einen portablen Header an.
knivil schrieb:
Warum ist das der falsche Weg, wenn der eine Standard (hier C++) etwas nicht hergibt, einen anderen (hier C99) zu verwenden?
Schon mal gehört, was ein C++ Kompiler ist? Der unterstützt den C++ Standard und keinen anderen Standard. Wenn er irgendetwas in der Richtung tut, dann sind das nicht portable Erweiterungen.
Grüssli
-
Dirkyy schrieb:
Welche Probleme könnten auftreten? Wie kann ich diese lösen?
Schau mal bei Wiki nach Endianess, sollte man auch bedenken.
-
Der unterstützt den C++ Standard und keinen anderen Standard. Wenn er irgendetwas in der Richtung tut, dann sind das nicht portable Erweiterungen.
Gut, dann gibt es nur eine Loesung: Es gibt keine Loesung in C++. Ansonsten: Diese Sachen einfach in einer C-Bibliothek kapseln, dafuer einen C-Compiler nutzen und dazulinken. Aber ich weiss grad nicht, ob der C++ Standard irgendwas uebers Linken aussagt ... Ich finde deine Argumentation zwar richtig, aber auch etwas engstirnig. Der Weg ueber stdint.h ist fuer mich der beste, wenn man exakte Groessen (nein, nicht 4 Byte oder mehr, sondern exakt 4 Byte) haben moechte. Was tun, wenn es auf 64 Bit Machinen keine 4 Byte gross ist und ich auf Bitoperationen vertraue, die nur fuer 4 Byte ausgelegt sind? ...
-
#include <cstring> #include <iostream> #include <algorithm> int main() { char buf[4]; std::cin.read(buf, sizeof(buf)); #ifdef CONVERT_ENDIAN std::reverse(buf, buf+sizeof(buf)); #endif std::size_t s; std::memcpy(reinterpret_cast<char*>(&s) #ifndef LITTLE_ENDIAN + sizeof(s)-sizeof(buf) #endif , buf, sizeof(buf)); std::cout << s << std::endl; }cstdint gibt es übrigens seit TR1

#include <algorithm> #include <iostream> #ifndef CPP0X #include <tr1/cstdint> using std::tr1::uint32_t; #else #include <cstdint> using std::uint32_t; #endif int main() { uint32_t i; std::cin.read(reinterpret_cast<char*>(&i), sizeof(i)); #ifdef CONVERT_ENDIAN std::reverse(reinterpret_cast<char*>(&i), reinterpret_cast<char*>(&i) + sizeof(i)); #endif std::cout << i << std::endl; }
-
knivil schrieb:
Gut, dann gibt es nur eine Loesung: Es gibt keine Loesung in C++.
Leider keine befriedigende, ja.
knivil schrieb:
Ansonsten: Diese Sachen einfach in einer C-Bibliothek kapseln, dafuer einen C-Compiler nutzen und dazulinken.
Geht auch nicht. Wie willst du dann auf den Typ zugreifen?
knivil schrieb:
Ich finde deine Argumentation zwar richtig, aber auch etwas engstirnig.
Naja, ich hebe nur den Finger. Du erzählst Dinge und setzt es so hin, als wenn sie portabel und überall korrekt wären, was schlicht und einfach nicht stimmt. Wenn du deine Lösungen mit Warnzeichen oder dem richtigen Kontext eingeschlossen hättest und auf die Probleme hingewiesen hättest, dann hätte ich nichts dagegen gesagt.
Es wurde nach einer portablen Lösung gefragt, was deine Lösungen allesamt nicht waren.
knivil schrieb:
Der Weg ueber stdint.h ist fuer mich der beste, wenn man exakte Groessen (nein, nicht 4 Byte oder mehr, sondern exakt 4 Byte) haben moechte. Was tun, wenn es auf 64 Bit Machinen keine 4 Byte gross ist und ich auf Bitoperationen vertraue, die nur fuer 4 Byte ausgelegt sind? ...
1. Du kannst mein präsentierter Code so umbauen, dass er die Überprüfung macht, ob es genau 4 Bytes sind

2. Man kann entsprechende Bit-Operationen durch AND-Bit-Operationen absichern. Mache ich fast immer, damit korrekt validiert wird.rüdiger schrieb:
cstdint gibt es übrigens seit TR1
Wusste ich nicht, danke für die Info! Wobei wenn ich weiterhin mit dem Finger weitermachen möchte: TR1 ist kein Standard, sondern nur ein Technical Report und muss nicht vorhanden sein, um dem C++ Standard 2003 zu genügen.

rüdiger schrieb:
... /* convert endianess */ ...Und was ist bei Middle-Endian? *SCNR*

Grüssli
-
Dravere schrieb:
Wusste ich nicht, danke für die Info! Wobei wenn ich weiterhin mit dem Finger weitermachen möchte: TR1 ist kein Standard, sondern nur ein Technical Report und muss nicht vorhanden sein, um dem C++ Standard 2003 zu genügen.

Der Op hat aber auch nichts von C++03 gesagt. Vielleicht sucht er ja eine portable Lösung für all seine C++0x Compiler :p. Vermutlich ist der eh geflohen und denkt wir sind alle verrückt :).
Dravere schrieb:
rüdiger schrieb:
... /* convert endianess */ ...Und was ist bei Middle-Endian? *SCNR*

Hmm, ich hätte eher gedacht, dass man sich darüber beschwert, wenn char keine 8 Bit hat :p
-
Danke für eure Antworten

Es ist für mich natürlich nicht direkt notwendig, dass ich exakt den Typ
size_tnutze. Ich kann also auch unsigned int schreiben oder einen anderen Typen, der diese Bedingungen erfüllt. Würde das einen Unterschied machen?Der Grund für die 4 Byte-Limitierung ist ein Dateiformat, dass ich unterstützen will und dies leider voraussetzt. Auch Bit-Operationen werden später ausgeführt.
Die von Rüdiger vorgeschlagene Absicherung ist zwar ganz nett, aber wenn ich das Programm (in kompilierter) Form weitergebe, dann bringt sie nichts mehr.
-
Dirkyy schrieb:
Es ist für mich natürlich nicht direkt notwendig, dass ich exakt den Typ
size_tnutze. Ich kann also auch unsigned int schreiben oder einen anderen Typen, der diese Bedingungen erfüllt. Würde das einen Unterschied machen?unsigned intwürde nicht viel bringen, da auchunsigned intnicht genau definiert ist. Am besten setzt du auf<tr1/cstdint>oder auf den Boost Header. Auch wenn sie nicht ganz portabel sind.Dirkyy schrieb:
Die von Rüdiger vorgeschlagene Absicherung ist zwar ganz nett, aber wenn ich das Programm (in kompilierter) Form weitergebe, dann bringt sie nichts mehr.
1. Rüdiger hat nur eine zusätzliche Methode präsentiert, wie man es einlesen könnte. Zudem hat er gezeigt, wie man mit Little- und Big-Endian umgehen kannt. Eine Absicherung hast du dort nicht.
2. In kompilierter Form ändern sich die Grössen nicht mehr. Wenn der Kompiler gesagt hat, dass einstd::size_t4 Bytes ist, dann wird das so in Assembler/Maschinencode hingeschrieben und wird auch so bleiben.Grüssli
-
Dirkyy schrieb:
Die von Rüdiger vorgeschlagene Absicherung ist zwar ganz nett, aber wenn ich das Programm (in kompilierter) Form weitergebe, dann bringt sie nichts mehr.
Warum das? Das zweite Beispiel benutzt doch einen Typ fester Größe. Beide Beispiele funktionieren unabhängig von der eigentlichen Größe von size_t.
Falls du die Endianess meinst: Wenn du auf einem System mit anderer Endianess arbeiten musst, dann musst du eh neu kompilieren.
Also beide Lösungen sollten funktionieren.
-
rüdiger schrieb:
Dirkyy schrieb:
Die von Rüdiger vorgeschlagene Absicherung ist zwar ganz nett, aber wenn ich das Programm (in kompilierter) Form weitergebe, dann bringt sie nichts mehr.
Warum das? Das zweite Beispiel benutzt doch einen Typ fester Größe. Beide Beispiele funktionieren unabhängig von der eigentlichen Größe von size_t.
Falls du die Endianess meinst: Wenn du auf einem System mit anderer Endianess arbeiten musst, dann musst du eh neu kompilieren.
Also beide Lösungen sollten funktionieren.
Mein Fehler, tut mir leid

Könntest du mir noch etwas zur Funktionsweise deines Codes sagen? Was hat es mit der Funktion
std::memcpyauf sich? Was wird dort wohin kopiert? Der Rest des Codes ist mir klar
Und kann ich die Idee dahinter auf andere (nicht portable) Typen auch anwenden?
-
Dirkyy schrieb:
Hey,
wie portabel ist size_t? Ich muss ein 4 Byte großes size_t aus einer Datei (binär) laden.
Binärdateien sind nicht portabel. Wenn es unbedingt ein Binärformat sein muß, dann muß man einen Header davorschreiben, in dem beschrieben ist, wie das Format aufgebaut ist. Bei den verbreiteten Plattformen hast Du vier verschiedene Formate für size_t: 32Bit und 64Bit sowie Big und Little Endian.