Ich möchte ein kleines Lernwerkzeug für SO vorbereiten, das Anfängern (und fortgeschrittenen Programmierern) helfen soll, ihre ungerechtfertigten Annahmen in C, C ++ und ihren Plattformen zu erkennen und in Frage zu stellen.
Beispiele:
- "ganze Zahlen wickeln sich um"
- "Jeder hat ASCII"
- "Ich kann einen Funktionszeiger in einer Leere speichern *"
Ich dachte mir, dass ein kleines Testprogramm auf verschiedenen Plattformen ausgeführt werden könnte, das die "plausiblen" Annahmen ausführt, die nach unserer Erfahrung in SO normalerweise von vielen unerfahrenen / halb erfahrenen Mainstream-Entwicklern getroffen werden, und die Art und Weise aufzeichnet, wie sie auf verschiedenen Maschinen brechen.
Ziel ist es nicht, zu beweisen, dass es "sicher" ist, etwas zu tun (was unmöglich wäre, die Tests beweisen nur etwas, wenn sie brechen), sondern selbst dem verständnislosesten Individuum zu demonstrieren, wie unauffällig der Ausdruck ist brechen Sie auf einem anderen Computer ab, wenn dieser ein undefiniertes oder implementierungsdefiniertes Verhalten aufweist. .
Um dies zu erreichen, möchte ich Sie fragen:
- Wie kann diese Idee verbessert werden?
- Welche Tests wären gut und wie sollten sie aussehen?
- Würden Sie die Tests auf den Plattformen ausführen, die Sie in die Hände bekommen und die Ergebnisse veröffentlichen können, damit wir eine Datenbank mit Plattformen erhalten, wie sie sich unterscheiden und warum dieser Unterschied zulässig ist?
Hier ist die aktuelle Version für das Testspielzeug:
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <stddef.h>
int count=0;
int total=0;
void expect(const char *info, const char *expr)
{
printf("..%s\n but '%s' is false.\n",info,expr);
fflush(stdout);
count++;
}
#define EXPECT(INFO,EXPR) if (total++,!(EXPR)) expect(INFO,#EXPR)
/* stack check..How can I do this better? */
ptrdiff_t check_grow(int k, int *p)
{
if (p==0) p=&k;
if (k==0) return &k-p;
else return check_grow(k-1,p);
}
#define BITS_PER_INT (sizeof(int)*CHAR_BIT)
int bits_per_int=BITS_PER_INT;
int int_max=INT_MAX;
int int_min=INT_MIN;
/* for 21 - left to right */
int ltr_result=0;
unsigned ltr_fun(int k)
{
ltr_result=ltr_result*10+k;
return 1;
}
int main()
{
printf("We like to think that:\n");
/* characters */
EXPECT("00 we have ASCII",('A'==65));
EXPECT("01 A-Z is in a block",('Z'-'A')+1==26);
EXPECT("02 big letters come before small letters",('A'<'a'));
EXPECT("03 a char is 8 bits",CHAR_BIT==8);
EXPECT("04 a char is signed",CHAR_MIN==SCHAR_MIN);
/* integers */
EXPECT("05 int has the size of pointers",sizeof(int)==sizeof(void*));
/* not true for Windows-64 */
EXPECT("05a long has at least the size of pointers",sizeof(long)>=sizeof(void*));
EXPECT("06 integers are 2-complement and wrap around",(int_max+1)==(int_min));
EXPECT("07 integers are 2-complement and *always* wrap around",(INT_MAX+1)==(INT_MIN));
EXPECT("08 overshifting is okay",(1<<bits_per_int)==0);
EXPECT("09 overshifting is *always* okay",(1<<BITS_PER_INT)==0);
{
int t;
EXPECT("09a minus shifts backwards",(t=-1,(15<<t)==7));
}
/* pointers */
/* Suggested by jalf */
EXPECT("10 void* can store function pointers",sizeof(void*)>=sizeof(void(*)()));
/* execution */
EXPECT("11 Detecting how the stack grows is easy",check_grow(5,0)!=0);
EXPECT("12 the stack grows downwards",check_grow(5,0)<0);
{
int t;
/* suggested by jk */
EXPECT("13 The smallest bits always come first",(t=0x1234,0x34==*(char*)&t));
}
{
/* Suggested by S.Lott */
int a[2]={0,0};
int i=0;
EXPECT("14 i++ is strictly left to right",(i=0,a[i++]=i,a[0]==1));
}
{
struct {
char c;
int i;
} char_int;
EXPECT("15 structs are packed",sizeof(char_int)==(sizeof(char)+sizeof(int)));
}
{
EXPECT("16 malloc()=NULL means out of memory",(malloc(0)!=NULL));
}
/* suggested by David Thornley */
EXPECT("17 size_t is unsigned int",sizeof(size_t)==sizeof(unsigned int));
/* this is true for C99, but not for C90. */
EXPECT("18 a%b has the same sign as a",((-10%3)==-1) && ((10%-3)==1));
/* suggested by nos */
EXPECT("19-1 char<short",sizeof(char)<sizeof(short));
EXPECT("19-2 short<int",sizeof(short)<sizeof(int));
EXPECT("19-3 int<long",sizeof(int)<sizeof(long));
EXPECT("20 ptrdiff_t and size_t have the same size",(sizeof(ptrdiff_t)==sizeof(size_t)));
#if 0
{
/* suggested by R. */
/* this crashed on TC 3.0++, compact. */
char buf[10];
EXPECT("21 You can use snprintf to append a string",
(snprintf(buf,10,"OK"),snprintf(buf,10,"%s!!",buf),strcmp(buf,"OK!!")==0));
}
#endif
EXPECT("21 Evaluation is left to right",
(ltr_fun(1)*ltr_fun(2)*ltr_fun(3)*ltr_fun(4),ltr_result==1234));
{
#ifdef __STDC_IEC_559__
int STDC_IEC_559_is_defined=1;
#else
/* This either means, there is no FP support
*or* the compiler is not C99 enough to define __STDC_IEC_559__
*or* the FP support is not IEEE compliant. */
int STDC_IEC_559_is_defined=0;
#endif
EXPECT("22 floating point is always IEEE",STDC_IEC_559_is_defined);
}
printf("From what I can say with my puny test cases, you are %d%% mainstream\n",100-(100*count)/total);
return 0;
}
Oh, und ich habe dieses Community-Wiki von Anfang an erstellt, weil ich dachte, dass die Leute mein Geschwätz bearbeiten wollen, wenn sie dies lesen.
UPDATE Vielen Dank für Ihre Eingabe. Ich habe einige Fälle aus Ihren Antworten hinzugefügt und werde sehen, ob ich einen Github dafür einrichten kann, wie Greg vorgeschlagen hat.
UPDATE : Ich habe dafür ein Github-Repo erstellt, die Datei lautet "gotcha.c":
Bitte antworten Sie hier mit Patches oder neuen Ideen, damit diese hier diskutiert oder geklärt werden können. Ich werde sie dann in gotcha.c zusammenführen.
quelle
dlsym()
ein void * zurückgegeben wird, aber sowohl für Daten- als auch für Funktionszeiger vorgesehen ist. Daher kann es nicht so schlimm sein, sich darauf zu verlassen.Antworten:
Die Reihenfolge der Auswertung von Unterausdrücken, einschließlich
+
,-
,=
,*
,/
), mit Ausnahme von:&&
und||
),?:
) und,
)ist nicht spezifiziert
Beispielsweise
quelle
boost::spirit
)+
Operators nicht angegeben ist (Compiler-Autoren müssen das Verhalten nicht dokumentieren). Es verstößt nicht gegen eine Sequenzpunktregel als solche.sdcc 29.7 / ucSim / Z80
printf stürzt ab. "O_O"
gcc 4.4@x86_64-suse-linux
gcc 4.4@x86_64-suse-linux (-O2)
clang 2.7@x86_64-suse-linux
open64 4.2.3@x86_64-suse-linux
Intel 11.1@x86_64-suse-linux
Turbo C ++ / DOS / Kleiner Speicher
Turbo C ++ / DOS / Mittlerer Speicher
Turbo C ++ / DOS / Kompaktspeicher
cl65 @ Commodore PET (Vizemulator)
Ich werde diese später aktualisieren:
Borland C ++ Builder 6.0 unter Windows XP
Visual Studio Express 2010 C ++ - CLR, Windows 7 64-Bit
(muss als C ++ kompiliert werden, da der CLR-Compiler kein reines C unterstützt)
MINGW64 (gcc-4.5.2-Vorlase)
- http://mingw-w64.sourceforge.net/
64-Bit-Windows verwendet das LLP64-Modell: Beide
int
undlong
sind als 32-Bit definiert, was bedeutet, dass keines für einen Zeiger lang genug ist.avr-gcc 4.3.2 / ATmega168 (Arduino Diecimila)
Die fehlgeschlagenen Annahmen sind:
Der Atmega168 verfügt über einen 16-Bit-PC, Code und Daten befinden sich jedoch in separaten Adressräumen. Größere Atmegas haben einen 22-Bit-PC!.
gcc 4.2.1 unter MacOSX 10.6, kompiliert mit -arch ppc
quelle
sizeof(void*)>=sizeof(void(*)())
wäre relevanter als ==. Alles , was wir über Pflege ist „können wir einen Funktionszeiger in einem void - Zeiger speichern“, so , ob die Annahme Sie testen müssen , ist einvoid*
ist mindestens so groß wie ein Funktionszeiger.sizeof(void*)>=sizeof(void(*)())
Vor langer Zeit unterrichtete ich C aus einem Lehrbuch, das hatte
als Beispielfrage. Er scheiterte für einen Studenten, weil die
sizeof
Renditen Werte des Typssize_t
, nichtint
,int
auf dieser Implementierung 16 Bit war undsize_t
war 32, und es war Big-Endian. (Die Plattform war Lightspeed C auf 680x0-basierten Macintosh-Computern. Ich sagte, es ist lange her.)quelle
unsigned long long
. Als Test 17 hinzugefügt.z
Modifikator fürsize_t
große Ganzzahlenlong long
nicht und wird auf einigen Plattformen auch nicht unterstützt. Es gibt also keine sichere tragbare Möglichkeit, die gedruckte Größe eines Objekts zu formatieren oder umzuwandeln.Sie müssen die
++
und--
Annahmen berücksichtigen, die die Leute machen.Zum Beispiel ist es syntaktisch legal, führt aber zu unterschiedlichen Ergebnissen, abhängig von zu vielen Dingen, um sie zu begründen.
Jede Anweisung mit
++
(oder--
) und einer Variablen, die mehrmals vorkommt, ist ein Problem.quelle
Sehr interessant!
Andere Dinge, die mir einfallen, könnten nützlich sein, um zu überprüfen:
Gibt es Funktionszeiger und Datenzeiger im selben Adressraum? (Bricht in Maschinen mit Harvard-Architektur wie dem kleinen DOS-Modus ein. Ich weiß jedoch nicht, wie Sie darauf testen würden.)
Wenn Sie einen NULL-Datenzeiger nehmen und ihn in den entsprechenden Integer-Typ umwandeln, hat er den numerischen Wert 0? (Pausen auf einigen wirklich alten Maschinen --- siehe http://c-faq.com/null/machexamp.html .) Das Gleiche gilt für den Funktionszeiger. Sie können auch unterschiedliche Werte sein.
Verursacht das Inkrementieren eines Zeigers über das Ende seines entsprechenden Speicherobjekts hinaus und dann wieder zurück sinnvolle Ergebnisse? (Ich kenne keine Maschinen, auf denen dies tatsächlich funktioniert, aber ich glaube, die C-Spezifikation erlaubt es Ihnen nicht einmal , an Zeiger zu denken , die weder auf (a) den Inhalt eines Arrays noch auf (b) das Element verweisen unmittelbar nach dem Array oder (c) NULL. Siehe http://c-faq.com/aryptr/non0based.html .)
führt der Vergleich zweier Zeiger mit unterschiedlichen Speicherobjekten mit <und> zu konsistenten Ergebnissen? (Ich kann mir vorstellen, dass dies auf exotischen segmentbasierten Maschinen nicht funktioniert. Die Spezifikation verbietet solche Vergleiche, sodass der Compiler berechtigt wäre, nur den versetzten Teil des Zeigers und nicht den Segmentteil zu vergleichen.)
Hmm. Ich werde versuchen, an etwas mehr zu denken.
Bearbeiten: Es wurden einige klarstellende Links zu den hervorragenden C-FAQ hinzugefügt.
quelle
Ich denke, Sie sollten sich bemühen, zwischen zwei sehr unterschiedlichen Klassen von "falschen" Annahmen zu unterscheiden. Eine gute Hälfte (Rechtsverschiebung und Vorzeichenerweiterung, ASCII-kompatible Codierung, Speicher ist linear, Daten- und Funktionszeiger sind kompatibel usw.) sind für die meisten C-Codierer ziemlich vernünftige Annahmen und können sogar als Teil des Standards enthalten sein Wenn C heute entworfen würde und wenn wir keinen alten IBM-Junk-Großvater hätten. Die andere Hälfte (Dinge im Zusammenhang mit Speicher-Aliasing, Verhalten von Bibliotheksfunktionen bei Überlappung von Eingabe- und Ausgabespeicher, 32-Bit-Annahmen wie Zeiger, die passen
int
oder die Sie verwenden könnenmalloc
Ohne Prototyp ist diese Aufrufkonvention für variadische und nicht-variadische Funktionen identisch. ...) Entweder im Widerspruch zu Optimierungen, die moderne Compiler durchführen möchten, oder zur Migration auf 64-Bit-Maschinen oder andere neue Technologien.quelle
malloc
ohne Prototyp<stdlib.h>
, dass ein Nein-Nein nicht berücksichtigt wird , wasmalloc
standardmäßig dazu führtint malloc(int)
, dass 64-Bit unterstützt werden soll.<stdlib.h>
, solange Sie einen anderen Header einfügen, der definiert,size_t
und dann selbstmalloc
mit einem korrekten Prototyp deklarieren .Hier ist eine lustige: Was ist mit dieser Funktion falsch?
[Antwort (rot13): Inevnqvp nethzragf borl gur byq X & E cebzbgvba ehyrf, juvpu zrnaf lbh pnaabg hfr 'sybng' (sei 'pune' sei 'fubeg') va in_net! Naq gur pbzcvyre vf erdhverq abg gb gerng guvf nf n pbzcvyr-gvzr reebe. (TPP qbrf rzvg n jneavat, gubhtu.)]
quelle
Ein anderer befasst sich mit dem Textmodus in
fopen
. Die meisten Programmierer gehen davon aus, dass entweder Text und Binär identisch sind (Unix) oder dass der Textmodus\r
Zeichen hinzufügt (Windows). C wurde jedoch auf Systeme portiert, die Datensätze mit fester Breite verwenden, bei denenfputc('\n', file)
in einer Textdatei Leerzeichen oder ähnliches hinzugefügt werden müssen, bis die Dateigröße ein Vielfaches der Datensatzlänge beträgt.Und hier sind meine Ergebnisse:
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3 auf x86-64
quelle
pow(2, n)
mit Bitoperationen kombiniert wurde .Einige von ihnen können nicht einfach in C getestet werden, da das Programm wahrscheinlich bei Implementierungen abstürzt, bei denen die Annahme nicht zutrifft.
"Es ist in Ordnung, mit einer Variablen mit Zeigerwert etwas zu tun. Sie muss nur dann einen gültigen Zeigerwert enthalten, wenn Sie ihn dereferenzieren."
Gleiches gilt für Integral- und Gleitkommatypen (außer
unsigned char
), die Trap-Darstellungen haben dürfen."Ganzzahlige Berechnungen werden umgangen. Dieses Programm gibt also eine große negative Ganzzahl aus."
(Nur C89.) "Es ist in Ordnung, am Ende von zu fallen
main
."quelle
gcc -ftrapv -O
die AusgabeWe like to think that:
Aborted
main
ohne Wert: Das Programm ist korrekt, gibt jedoch einen undefinierten Beendigungsstatus zurück (C89 §2.1.2.2). Bei vielen Implementierungen (wie gcc und älteren Unix-Compilern) erhalten Sie alles, was sich zu diesem Zeitpunkt in einem bestimmten Register befand. Das Programm funktioniert normalerweise so lange, bis es in einem Makefile oder einer anderen Umgebung verwendet wird, die den Beendigungsstatus überprüft.Nun, die klassischen Portabilitätsannahmen, die noch nicht gemeint sind, sind
quelle
short
Wertes fedcab9876543210 (das sind 16 Binärziffern) als die beiden Bytes 0248ace und fdb97531.Diskretisierungsfehler aufgrund von Gleitkommadarstellung. Wenn Sie beispielsweise die Standardformel verwenden, um quadratische Gleichungen zu lösen, oder endliche Differenzen, um Ableitungen zu approximieren, oder die Standardformel, um Varianzen zu berechnen, geht die Genauigkeit aufgrund der Berechnung von Differenzen zwischen ähnlichen Zahlen verloren. Der Gauß-Algorithmus zum Lösen linearer Systeme ist schlecht, da sich Rundungsfehler ansammeln. Daher werden QR- oder LU-Zerlegung, Cholesky-Zerlegung, SVD usw. verwendet. Das Hinzufügen von Gleitkommazahlen ist nicht assoziativ. Es gibt denormale, unendliche und NaN-Werte. a + b - a ≠ b .
Zeichenfolgen: Unterschied zwischen Zeichen, Codepunkten und Codeeinheiten. Wie Unicode auf den verschiedenen Betriebssystemen implementiert ist; Unicode-Codierungen. Das Öffnen einer Datei mit einem beliebigen Unicode-Dateinamen ist mit C ++ nicht portabel möglich.
Rennbedingungen, auch ohne Threading: Wenn Sie testen, ob eine Datei vorhanden ist, kann das Ergebnis jederzeit ungültig werden.
ERROR_SUCCESS
= 0quelle
Fügen Sie eine Prüfung für ganzzahlige Größen hinzu. Die meisten Leute gehen davon aus, dass ein int größer als ein Short größer als ein Char ist. Diese können jedoch alle falsch sein:
sizeof(char) < sizeof(int); sizeof(short) < sizeof(int); sizeof(char) < sizeof(short)
Dieser Code schlägt möglicherweise fehl (stürzt bei nicht ausgerichtetem Zugriff ab)
quelle
int *p = (int*)&buf[1];
in C ++ tun , die Leute erwarten, dass das auch funktioniert.sizeof(char) < sizeof(int)
Wird benötigt. Beispielsweise gibt fgetc () den Wert des Zeichens als vorzeichenloses Zeichen zurück, das in int konvertiert wurde oderEOF
ein negativer Wert ist.unsigned char
Möglicherweise sind keine Füllbits vorhanden. Dies kann also nur erreicht werden, indem int größer als char gemacht wird. Außerdem erfordern (die meisten Versionen von) der C-Spezifikation, dass jeder Wert aus dem Bereich -32767..32767 in einem int gespeichert werden kann.Einige Dinge zu integrierten Datentypen:
char
undsigned char
sind tatsächlich zwei verschiedene Typen (im Gegensatz zuint
undsigned int
die sich auf denselben vorzeichenbehafteten Ganzzahltyp beziehen).-3/5
könnte zurückkehren0
oder-1
. Eine Rundung gegen Null für den Fall, dass ein Operand negativ war, ist nur in C99 nach oben und C ++ 0x nach oben garantiert.int
hat mindestens 16 Bit, along
hat mindestens 32 Bit, along long
hat mindestens 64 Bit. Afloat
kann mindestens 6 höchstwertige Dezimalstellen korrekt darstellen. Adouble
kann mindestens 10 höchstwertige Dezimalstellen korrekt darstellen.Zugegeben, auf den meisten Maschinen haben wir zwei Komplemente und IEEE 754-Floats.
quelle
int mult(int a,int b) { return (long)a*b;}
[z. B. wennint
32 Bit, aber Register undlong
64] generiert werden. Ohne eine solche Anforderung, die „natürliche“ Verhalten der schnellsten Implementierunglong l=mult(1000000,1000000);
würde eingestelltl
gleich1000000000000
, auch wenn das eine „unmögliche“ Wert für eine istint
.Wie wäre es mit diesem:
Kein Datenzeiger kann jemals mit einem gültigen Funktionszeiger identisch sein.
Dies ist WAHR für alle flachen Modelle, MS-DOS TINY-, LARGE- und HUGE-Modelle, falsch für MS-DOS SMALL-Modelle und fast immer falsch für MEDIUM- und COMPACT-Modelle (abhängig von der Ladeadresse benötigen Sie ein wirklich altes DOS mach es wahr).
Ich kann dafür keinen Test schreiben
Und noch schlimmer: Zeiger, die in ptrdiff_t umgewandelt wurden, können verglichen werden. Dies gilt nicht für das MS-DOS LARGE-Modell (der einzige Unterschied zwischen LARGE und HUGE besteht darin, dass HUGE Compiler-Code zum Normalisieren von Zeigern hinzufügt).
Ich kann keinen Test schreiben, da die Umgebung, in der diese Bomben hart sind, keinen Puffer größer als 64 KB zuweist, sodass der Code, der dies demonstriert, auf anderen Plattformen abstürzt.
Dieser spezielle Test würde ein inzwischen nicht mehr funktionierendes System weitergeben (beachten Sie, dass dies von den Interna von malloc abhängt):
quelle
BEARBEITEN: Auf die letzte Version des Programms aktualisiert
Solaris-SPARC
gcc 3.4.6 in 32 bit
gcc 3.4.6 in 64 bit
und mit SUNStudio 11 32 Bit
und mit SUNStudio 11 64 Bit
quelle
Sie können text-mode (
fopen("filename", "r")
) verwenden, um jede Art von Textdatei zu lesen.Während dies theoretisch gut funktionieren sollte
ftell()
, werden in einigen Versionen der Windows-Standardbibliothekftell()
häufig ungültige Werte zurückgegeben , wenn Sie sie auch in Ihrem Code verwenden und Ihre Textdatei UNIX-artige Zeilenenden aufweist . Die Lösung besteht darin, stattdessen den Binärmodus zu verwenden (fopen("filename", "rb")
).quelle
gcc 3.3.2 unter AIX 5.3 (ja, wir müssen gcc aktualisieren)
quelle
Eine Annahme, die einige in C ++ machen können, ist, dass a auf
struct
das beschränkt ist, was es in C kann. Tatsache ist, dass a in C ++struct
wie a ist,class
außer dass es standardmäßig alles öffentlich hat.C ++ Struktur:
quelle
Standard-Mathematikfunktionen auf verschiedenen Systemen liefern keine identischen Ergebnisse.
quelle
Visual Studio Express 2010 auf 32-Bit x86.
quelle
Über Codepad.org (
C++: g++ 4.1.2 flags: -O -std=c++98 -pedantic-errors -Wfatal-errors -Werror -Wall -Wextra -Wno-missing-field-initializers -Wwrite-strings -Wno-deprecated -Wno-unused -Wno-non-virtual-dtor -Wno-variadic-macros -fmessage-length=0 -ftemplate-depth-128 -fno-merge-constants -fno-nonansi-builtins -fno-gnu-keywords -fno-elide-constructors -fstrict-aliasing -fstack-protector-all -Winvalid-pch
).Beachten Sie, dass Codepad nicht hatte
stddef.h
. Ich habe Test 9 aufgrund eines Codepads entfernt und Warnungen als Fehler verwendet. Ich habe diecount
Variable auch umbenannt , da sie aus irgendeinem Grund bereits definiert wurde.quelle
Wie wäre es mit einer Verschiebung nach rechts um übermäßige Beträge - ist dies nach dem Standard zulässig oder einen Test wert?
Gibt Standard C das Verhalten des folgenden Programms an:
Auf mindestens einem von mir verwendeten Compiler schlägt dieser Code fehl, es sei denn, das Argument für print_string ist "char const *". Erlaubt der Standard eine solche Einschränkung?
Einige Systeme erlauben es einem, Zeiger auf nicht ausgerichtete Ints zu erzeugen, andere nicht. Könnte einen Test wert sein.
quelle
<<
und>>
). C99 hat in §6.5.7-3 die gleiche Sprache.putch
(warum haben Sie den Standard nicht verwendetputchar
?) Kann ich in Ihrem Programm kein undefiniertes Verhalten feststellen. C89 §3.1.4 legt fest, dass „ein Zeichenfolgenliteral vom Typ […] 'Array of char' hat“ (Anmerkung: neinconst
) und dass „wenn das Programm versucht, ein Zeichenfolgenliteral zu ändern […], das Verhalten undefiniert ist“. . Welcher Compiler ist das und wie übersetzt er dieses Programm?Zu Ihrer Information: Für diejenigen, die ihre C-Kenntnisse in Java übersetzen müssen, sind hier einige Fallstricke.
In Java ist char 16-Bit und signiert. Byte ist 8-Bit und signiert.
long ist immer 64-Bit, Referenzen können 32-Bit- oder 64-Bit-Referenzen sein (wenn Sie mehr als eine App mit mehr als 32 GB haben). 64-Bit-JVMs verwenden normalerweise 32-Bit-Referenzen.
Die Verschiebung wird maskiert, so dass i << 64 == i == i << -64, i << 63 == i << -1
ByteOrder.nativeOrder () kann BIG_ENDIAN oder LITTLE_ENDIAN sein
i = i++
Ändert sich niei
Die Größe von Sammlungen und Arrays beträgt immer 32-Bit, unabhängig davon, ob die JVM 32-Bit oder 64-Bit ist.
char ist 16-Bit, short ist 16-Bit, int ist 32-Bit und long ist 64-Bit.
quelle