Skalare Datentypen - irgendeine Verlässlichkeit?
-
Guten Abend,
Wie handhabt ihr das mit den einfachen Datentypen? Man kann sich dank dem grosszügigen Standard ja nie sicher sein, wieviele Byte ein Typ einnimt und wie gross dessen Wertebereich ist.
Wie kann man so einigermassen portabel programmieren? Es ist ja nicht einmal sichergestellt, dass ein Zeiger eine Integer-Adresse beinhaltet. Auch
int
könnte theoretisch sehr wenige Zahlen umfassen. Nehmt ihr immer entsprechende unabhängige Typedefs? Oder macht ihr einfach (Static-)Assertions bei den Limits? Ich bin bei mir einfach davon ausgegangen, dassshort
65536 undint
etwas mehr als 4 Milliarden Zustände haben kann. Aber ich programmiere auch hauptsächlich für mich selber und wechsle den Compiler nicht, von daher ist das nicht so relevant.Aber wenn man das wirklich korrekt machen wollte: Welchen Sinn haben dann die skalaren Datentypen noch, wenn man sich ja doch nie sicher sein kann?
Und weshalb hat der C++-Standard diesbezüglich nicht mehr Vorschriften gemacht? Dass
int
oft den für die Plattform am besten ausgerichteten Datentypen repräsentiert, ist ja schön und gut, aber etwas vage...
-
mh gute frage
ich programmiere auch sehr viel (ok, eigendlich nur) für mich selbst und demnach kümmere ich mich auch kaum um kompatiblität
aber eigendlich sollte der standart so genau sein dass man windows code auch auf linux compilen kann und auch was anständiges rausbekommt
und naja in den nächsten jahren wird int ja wenn grösser werden statt kleiner und von daher ists ja eigendlich verschmerzbarund wenn man mal einen zeiger speichern will sollte man schon klassen dafür haben...
-
Skym0sh0 schrieb:
und naja in den nächsten jahren wird int ja wenn grösser werden statt kleiner und von daher ists ja eigendlich verschmerzbar
Ja, die Tendenz stimmt schon. Das heisst trotzdem nicht, dass man sich nicht mehr achten muss...
Skym0sh0 schrieb:
und wenn man mal einen zeiger speichern will sollte man schon klassen dafür haben...
Wie meinst du das? Es gibt Situationen, in denen man nicht um rohe Zeiger herumkommt. Abgesehen davon: Was ändern Klassen, die um einen Zeiger gepackt sind, an der Flexibilität des Wertebereichs beziehungsweise der internen Repräsentation des Speichers?
-
Hmm. Im Buch von Stroustrup sagt er, dass char mindestens 8 Bit hat, short mindestens 16 Bit und long 32 Bit hat. Allerdings habe ich im Standard nichts gefunden, was auf dieser Werte weist.
Das hier besagt lediglich, dass ein char ( in C++ byte genannt) mindestens 8 Bit haben muss. (wegen dem Character set)
14882 schrieb:
1.7 The C+ + memory model [intro.memory]
1 The fundamental storage unit in the C + + memory model is the byte. A byte is at least large enough to contain
any member of the basic execution character set and is composed of a contiguous sequence of bits, the
number of which is implementation-defined. The least significant bit is called the low-order bit; the most
significant bit is called the high-order bit. The memory available to a C + + program consists of one or more
sequences of contiguous bytes. Every byte has a unique address.Etwas genaueres konnte ich leider nicht finden.
-
boost to the rescue: http://www.boost.org/doc/libs/1_37_0/libs/integer/index.html
und ab C++0x ist <cstdint> dann ja sogar ein offizieller Header
-
Naja, aber mir ging es ja eher um die Built-Ins.
Benutzt ihr trotz allem immer
int
,short
, etc.? Oder bei allen unsigned-Typensize_t
? Oder die <cstdint>- bzw. <stdint.h>-Typen?Ich finde es einfach ein wenig fragwürdig, dass die Sprache Typen bereitstellt, von denen erwartet wird, dass man mit ihnen arbeitet, aber gleichzeitig kann man sich dabei nie ganz sicher sein...
-
Nexus schrieb:
Naja, aber mir ging es ja eher um die Built-Ins.
Benutzt ihr trotz allem immer
int
,short
, etc.? Oder bei allen unsigned-Typensize_t
? Oder die <cstdint>- bzw. <stdint.h>-Typen?size_t, etc. wenn es vom Kontext her Sinn macht.
Nexus schrieb:
Ich finde es einfach ein wenig fragwürdig, dass die Sprache Typen bereitstellt, von denen erwartet wird, dass man mit ihnen arbeitet, aber gleichzeitig kann man sich dabei nie ganz sicher sein...
Du kannst dir sicher sein. Wie schon gesagt.
char
hat mindestens 8 Bit,short
mindestens 16 undlong
mindestens 32. Sie dürfen natürlich größer sein. Aber das sollte in fast allen Fällen nicht schlimm sein.Wenn du
int
verwendest, wird dir was anderes garantiert. Und zwar, dass (soweit ich mich erinnere) er mindestens so lang wie short ist. Und dass er den nativen Integertyp des Prozessors wiederspiegelt. Also das beste ist, womit der Prozessor umgehen kann (unter der Voraussetzung, dass er halt mit mind. 16-Bit umgehen kann).Das ist doch eigentlich recht vernünftig. Eine gewisse Sache ist garantiert, aber es kann auch besser sein.
-
ProgChild schrieb:
Nexus schrieb:
Ich finde es einfach ein wenig fragwürdig, dass die Sprache Typen bereitstellt, von denen erwartet wird, dass man mit ihnen arbeitet, aber gleichzeitig kann man sich dabei nie ganz sicher sein...
Du kannst dir sicher sein. Wie schon gesagt.
char
hat mindestens 8 Bit,short
mindestens 16 undlong
mindestens 32. Sie dürfen natürlich größer sein. Aber das sollte in fast allen Fällen nicht schlimm sein.Ich glaube in dem Fall zwar einmal, dass Stroustrup da nichts falsches geschrieben hat, aber im Standard konnte ich von diesen Werten nichts finden.
Wie gesagt die einzige Garantie, die ich gefunden habe, ist, dass char mindestens 8 Bit haben muss, damit es das Characterset halten kann.
-
Die Mindestgrößen werden indirekt über die Mindesgrößen von den *_MAX und *_MIN Konstanten aus climits garantiert. SHRT_MAX muss z.B. mindestens 32767 groß sein. Die Mindestgröße für short ist also 16-bit.
Gruß
Don06
-
-
drakon schrieb:
Ich glaube in dem Fall zwar einmal, dass Stroustrup da nichts falsches geschrieben hat, aber im Standard konnte ich von diesen Werten nichts finden.
Wie gesagt die einzige Garantie, die ich gefunden habe, ist, dass char mindestens 8 Bit haben muss, damit es das Characterset halten kann.Ich hab auch gerade im Standard gewühlt und nichts gefunden. Aber ich hab auch die 800 Seiten nicht komplett gelesen
Ich hab das aber auch irgenwo gelesen, dass das mit den Variablen so garantiert ist.
-
ProgChild schrieb:
Wenn du
int
verwendest, wird dir was anderes garantiert. Und zwar, dass (soweit ich mich erinnere) er mindestens so lang wie short ist. Und dass er den nativen Integertyp des Prozessors wiederspiegelt. Also das beste ist, womit der Prozessor umgehen kann (unter der Voraussetzung, dass er halt mit mind. 16-Bit umgehen kann).Das heisst,
int
sollte man um sicher zu gehen nur nutzen, wenn man gerade so gutshort
nutzen könnte. Naja, dann habe ich das bisher etwas missachtet. Naja...Don06 schrieb:
Die Mindestgrößen werden indirekt über die Mindesgrößen von den *_MAX und *_MIN Konstanten aus climits garantiert. SHRT_MAX muss z.B. mindestens 32767 groß sein. Die Mindestgröße für short ist also 16-bit.
Okay. Wo findet man dann die tatsächlichen Grössen? Sind die Werte in
<limits>
eigentlich immer genau die gleichen wie die in<climits>
?
-
Wie "portabel" willst du denn programmieren und warum interessiert dich das so genau wie groß ein Datentyp ist? Wenn du für normale Windows,Linux oder Mac PCs programmierst, sind die doch sogut wie gleich groß und es ist egal. Wenn du für embedded Hardware programmierst weiß du auch wie groß dort die Datentypen sind. Ich vesteh nicht was da so ein großes Problem ist.
-
sagmal schrieb:
Wie "portabel" willst du denn programmieren und warum interessiert dich das so genau wie groß ein Datentyp ist?
Weil es von Vorteil wäre, wenn ich meine Programme nicht mühsam durchforsten und Typen ersetzen müsste, wenn ich sie mal auf einer anderen Plattform zum Laufen bringen will.
sagmal schrieb:
Wenn du für normale Windows,Linux oder Mac PCs programmierst, sind die doch sogut wie gleich groß und es ist egal.
Das würde ich nicht sagen. Meines Wissens haben doch bereits die verschiedenen Compiler/IDEs unterschiedliche Typen. Unterscheiden sich nicht bereits MSVC++ und Code::Blocks, zum Beispiel bezüglich
long double
?
-
Nexus schrieb:
sagmal schrieb:
Wie "portabel" willst du denn programmieren und warum interessiert dich das so genau wie groß ein Datentyp ist?
Weil es von Vorteil wäre, wenn ich meine Programme nicht mühsam durchforsten und Typen ersetzen müsste, wenn ich sie mal auf einer anderen Plattform zum Laufen bringen will.
sagmal schrieb:
Wenn du für normale Windows,Linux oder Mac PCs programmierst, sind die doch sogut wie gleich groß und es ist egal.
Das würde ich nicht sagen. Meines Wissens haben doch bereits die verschiedenen Compiler/IDEs unterschiedliche Typen. Unterscheiden sich nicht bereits MSVC++ und Code::Blocks, zum Beispiel bezüglich
long double
?was für Programme schreibst du denn, dass es so wichtig ist, dass du die Datentypen immer voll ausnutzen kannst und sogar long double brauchst?
-
Aus meinem ersten Post sollte der Beweggrund für diesen Thread ersichtlich sein.
-
Nexus schrieb:
Und weshalb hat der C++-Standard diesbezüglich nicht mehr Vorschriften gemacht? Dass
int
oft den für die Plattform am besten ausgerichteten Datentypen repräsentiert, ist ja schön und gut, aber etwas vage...Das hängt alles von C ab.
Aber etwas aus der C++ Norm.
§ 3.9.1 Absatz 2
kann man folgende Reihenfolge schließen
sizeof(signed char) <= sizeof(short) <= sizeof(int) <= sizeof(long int)
Absatz 3 ditto für vorzeichenlose TypenDesweiteren ist ISO 9899:2001 § 5.2.4.2.1 zu beachten
CHAR_BIT >= 8 SCHAR_MIN <= -127 SCHAR_MAX >= 127 UCHAR_MAX >= 255 SHRT_MIN <= -32767 SHRT_MAX >= 32767 USHRT_MAX >= 65535 INT_MIN <= -32767 INT_MAX >= 32767 UINT_MAX >= 65535 LONG_MIN <= -2147483647 LONG_MAX >= +2147483647 ULONG_MAX >= 4294967295 LLONG_MIN <= -9223372036854775807 LLONG_MAX >= 9223372036854775807 ULLONG_MAX >= 18446744073709551615
Wenn diese Aussagen nicht ausreichen, dann muß man sich mit <stdint.h> auseinandersetzen. Es gibt darin Datentypen mit exakten Bitgrößen und Datentypen mit mindestens n-Bitgröße.
Folgendes muß definiert sein.int_least8_t int_least16_t int_least32_t int_least64_t uint_least8_t uint_least16_t uint_least32_t uint_least64_t
Falls die Integer-Typen mit 8, 16, 32 und 64Bitgröße als Standardtypen existieren, muß es die folgenden typedefs geben.
int8_t, uint8_t, ... , int64_t, uint64_tFolgendes muß wiederrum definiert sein
int_fast8_t int_fast16_t int_fast32_t int_fast64_t uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t
Wenn Dir das nicht genügt, dann kannst Du Dich auf die SUS V3 (Single UNIX Spec V3) beziehen (keine Ahnung was für Garantien Windows macht). Natürlich läuft dann Dein Programm nur noch garantiert auf einer SUS V3 Plattform.
SUSV3 definiert im Prinzip zwei Laufzeitumgebungen ILP32 und LP64.
Auszug aus "The UNIX System Today" (SUS V2)
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(size_t)
Die typedefs int8_t, int16_t, int32_t (und korrespondierende uint) sind definiert, falls _POSIX_V6_ILP32_OFFBIG, _POSIX_V6_LP64_OFF64 oder _POSIX_V6_LPBIG_OFFBIG definiert wurden ist auch uint64_t bzw. int64_t definiert.ILP32 definiert die Bit größen der Typen wie folgt:
char 8, short 16, int 32, long 32, pointer 32
LP64:
char 8, short 16, int 32, long 64, pointer 64Es gibt die Möglichkeit, daß ein 64Bit Type im ILP32 Modus definiert ist, aber das hängt dann von bestimmten Makros ab, dazu bitte die SUS lesen.
-
Vielen Dank für die ausführliche Antwort, ~john! Das ist echt interessant, vieles davon habe ich nicht gewusst.
Wenn man jetzt
char
,short
undlong
für Integer nutzt, sollte man die Grösse eigentlich relativ gut eingrenzen können. Ansonsten die <stdint.h>-Typen... Danke für eure Bemühungen!
-
int ist nicht der "native" Datentyp des Prozessors.
(1) Der Begriff an sich ist schon relativ sinnfrei, weil es dem x86 oder x86-64 egal ist, ob er jetzt mit dem 8, 16, 32 Teil des Registers rechnet. Die Größen sind alle "native" weil sie alle im Assembler direkt als Operand angegeben werden können (es muss nicht zum Beispiel ein 16Bit Wert vorher in ein 32 Bit Register kopiert werden, welches dann mit Nullen aufgefüllt wird).
(2) Wenn man diesen Begriff trotzdem verwendet, müsste ein int für den x86-64 ja 64 Bit haben, ich kennen keinen Compiler der das so macht. Der g++ und VC++ jedenfalls nicht.
-
Optimizer schrieb:
int ist nicht der "native" Datentyp des Prozessors.
(1) Der Begriff an sich ist schon relativ sinnfrei, weil es dem x86 oder x86-64 egal ist, ob er jetzt mit dem 8, 16, 32 Teil des Registers rechnet. Die Größen sind alle "native" weil sie alle im Assembler direkt als Operand angegeben werden können (es muss nicht zum Beispiel ein 16Bit Wert vorher in ein 32 Bit Register kopiert werden, welches dann mit Nullen aufgefüllt wird).
(2) Wenn man diesen Begriff trotzdem verwendet, müsste ein int für den x86-64 ja 64 Bit haben, ich kennen keinen Compiler der das so macht. Der g++ und VC++ jedenfalls nicht.
Andersherum wird ein Schuh draus. Compilierst du für einen 16-Bit-Prozessor wird
int
wohl kaum 32-Bit groß sein. Compilierst du für einen 32-Bit Prozessor, wirdint
wohl kaum 64-Bit groß sein. Und auf einem 16-Bit System kann sehr wohl der Datentyplong
vorhanden sein.Die Welt besteht ja nicht nur aus x86 und x64.