2009-06-25 6 views
6

Sagen wir, ich programmiere in Java oder Python oder C++ für ein einfaches Problem, könnte ein TCP/UDP-Echo-Server oder die Berechnung von Fakultät sein. Muss ich mich um die Architekturdetails kümmern, d. H. Ob es 32 oder 64 Bit ist?Müsste man die Maschinenarchitektur kennen, um Code zu schreiben?

IMHO, es sei denn, ich programmieren etwas mit ziemlich Low-Level-Sachen zu tun, dann muss ich nicht stören, wenn es 32 oder 64 Bit ist. Wo gehe ich falsch? Oder bin ich richtig ???

+0

Kennen Sie überhaupt den Sinn von Sprachen wie Java? Es läuft praktisch unverändert auf allen unterstützten Plattformen ohne Programmänderungen. –

+0

Der Vergleich von Java mit C++ in Bezug auf die Plattformunabhängigkeit zeigt ein mangelndes Verständnis für die Vor- und Nachteile der genannten Sprachen/Plattformen. –

+0

Die genannten Sprachen sind nur Beispiele! Ich vergleiche oder kritisiere nicht! – g06lin

Antwort

15

richtig für die meisten Umstände

Die Runtime/Sprache/Compiler abstrakt diese Details, wenn Sie direkt mit Wortgrößen oder binär auf einem niedrigen Niveau zu tun.

Sogar byteorder wird vom NIC/Netzwerk-Stack im Kernel abstrahiert. Es ist für dich übersetzt. Bei der Programmierung von Sockets in C müssen Sie beim Senden von Daten manchmal mit der Byte-Reihenfolge für das Netzwerk umgehen ... aber das betrifft keine 32- oder 64-Bit-Unterschiede. Wenn Sie mit Blobs von Binärdaten umgehen, kann das Mapping von einer Architektur zur anderen (als Überlagerung zu einer C-Struktur zum Beispiel) zu Problemen führen, wie andere bereits erwähnt haben. Aus diesem Grund entwickeln wir architekturunabhängige Protokolle basierend auf Zeichen und so weiter.

Tatsächlich Dinge wie Java in einer virtuellen Maschine ausgeführt, die die Maschine abstrahiert ein weiterer Schritt!

Das Wissen um ein Bit über den Befehlssatz der Architektur und wie die Syntax kompiliert wird, kann Ihnen helfen, die Plattform zu verstehen und saubereren, engeren Code zu schreiben. Ich weiß, dass ich nach dem Studium von Compilern einen alten C-Code verzog.

+2

Die Prozessor-Hardware ist Ihnen seit Jahren nicht mehr bewusst. Habe ich nicht gewusst oder musste es wissen, seit ich das letzte Mal Echtzeit-Controller für Militärwaffen geschrieben habe. –

+1

"Echtzeit-Controller für militärische Waffen" - Super! –

0

Sie müssen über „Bytereihenfolge“ nur kümmern, wenn Sie rohe C structs über den Draht wie

 
ret = send(socket, &myStruct, sizeof(myStruct)); 

senden und empfangen Dies ist jedoch nicht empfohlen.

Es wird empfohlen, dass Sie ein Protokoll zwischen den Parteien definieren, so dass es keine Rolle spielt die Maschinenarchitekturen der Parteien.

+0

Nein, es ist viel schlimmer als das. Sie müssen Endianess wissen, wenn Sie Binärdaten in Dateien lesen oder schreiben, und es spielt keine Rolle, ob sie in Strukturen sind oder nicht. –

+0

Wenn Sie in Binärdateien schreiben, haben Sie bereits ein Protokoll vereinbart, dass beide Parteien miteinander kommunizieren. Das Protokoll ist das Dateiformat. – Reginaldo

0

In C++ müssen Sie sehr vorsichtig sein, wenn Sie Code schreiben möchten, der gleichgültig auf 32 oder 64 Bits funktioniert. Viele Menschen gehen fälschlicherweise davon aus, dass int beispielsweise einen Zeiger speichern kann.

+0

Ich hatte noch nie Probleme damit. Ich hatte im Laufe der Jahre Probleme mit Leuten, die dachten, dass int gleich size_t ist. –

+1

Wird die Breite eines Typs nicht vorausgesetzt (wenn es nicht übereinstimmt), nur schlechte Programmierpraxis? : P –

+1

Oh, ja, ist es. Es ist jedoch übliche Programmierpraxis. Ich bemerkte es zuerst, als ich von einem Lehrbuch lehrte, das vorschlug, "printf" auszuprobieren ("Größe von int ist% d \ n", sizeof (int)); " und ein Student wurde Null ausgedruckt - auf einem Big-Endian-System, wo Int 16 Bits und Größe_t 32 war. –

15

Wissen, wie die Dinge funktionieren, wie die virtuelle Maschine funktioniert und wie sie auf Ihrer Plattform funktioniert oder wie bestimmte C++ - Konstrukte in Assembly umgewandelt werden, macht Sie immer zu einem besseren Programmierer, weil Sie verstehen, warum Dinge so sein sollten so gemacht wie sie sind.

Sie müssen Dinge wie Speicher verstehen, um zu wissen, was Cache-Misses sind und warum diese Ihr Programm beeinflussen könnten. Sie sollten wissen, wie bestimmte Dinge implementiert werden, auch wenn Sie nur eine Schnittstelle oder einen High-Level-Weg verwenden, um zu erreichen. Wenn Sie wissen, wie es funktioniert, werden Sie sicher sein, dass Sie es auf die beste Weise tun.

Für die Paketarbeit müssen Sie verstehen, wie Daten auf Plattformen gespeichert werden und wie das Senden über das Netzwerk an eine andere Plattform das Lesen der Daten ändern kann (Endian-Ness).

Ihr Compiler wird die Plattform, auf der Sie kompilieren, am besten nutzen. Solange Sie sich an Standards halten und gut programmieren, können Sie die meisten Dinge ignorieren und annehmen, dass der Compiler das Beste herauspeitscht.

Also kurz gesagt, nein. Sie müssen nicht die Low-Level-Zeug wissen, aber es nie tut weh zu wissen.

+0

Ich stimme völlig mit Ihnen überein! – g06lin

+1

Das letzte Bit ist sehr gut formuliert: "Es tut nie weh zu wissen" – BCS

1

Wenn Sie in Python oder in Java programmieren, abstrahieren der Interpreter und die virtuelle Maschine diese Schicht der Architektur. Sie müssen sich dann keine Sorgen machen, wenn es auf einer 32- oder 64-Bit-Architektur läuft.

Das gleiche kann nicht für C++ gesagt werden, in dem man sich fragen müssen, werden manchmal, wenn Sie auf einem 32 oder 64-Bit-Computer ausgeführt werden

3

In Java und Python, Architektur Details abstrahiert so entfernt, dass es ist tatsächlich mehr oder weniger unmöglich, architekturabhängigen Code zu schreiben.

Mit C++ ist dies eine ganz andere Sache - Sie können sicherlich Code schreiben, der nicht von Architekturdetails abhängt, aber Sie müssen Acht geben, Fallstricke zu vermeiden, speziell in Bezug auf grundlegende Datentypen, die architekturabhängig sind int.

6

Sie müssen manchmal stören.

Sie können überrascht sein, wenn diese Low-Level-Details plötzlich herausspringen und Sie beißen. Zum Beispiel standardisierte Java double als 64 Bit. Linux JVM verwendet jedoch den Modus "Erweiterte Genauigkeit", wenn das Doppelte 80 Bit lang ist, solange es sich im CPU-Register befindet. Dies bedeutet, dass der folgende Code fehlschlagen:

double x = fun1(); 
double y = x; 

System.out.println(fun2(x)); 

assert(y == x); 

Ganz einfach, weil y aus dem Register in dem Speicher und trunkiert 80-64 Bits gezwungen wird.

+1

Bedeutet dies nicht, dass die Linux JVM nicht Standard ist? IIRC, definiert Java Gleitkommaoperationen sehr detailliert –

+1

Dieses Beispiel zeigt etwas anderes - der Implementierer der Sprachlaufzeit muss die Sprachdefinition richtig verstehen, das ist einfach kaputt, das sollte kein Java-Programmierer hinnehmen müssen –

+2

Ja, das ist ein Fehler Dies wurde als Fehler in GNU Java gemeldet, aber ignoriert: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16122 –

2

Solange Sie die Dinge richtig machen, müssen Sie fast nie für die meisten Sprachen wissen. In vielen Fällen müssen Sie das nie wissen, da das Sprachverhalten nicht variiert (z. B. spezifiziert Java das Laufzeitverhalten genau).

In C++ und C, Dinge richtig zu tun, enthält keine Annahmen über int. Setze keine Zeiger in int, und wenn du etwas mit Speichergrößen oder Adressen machst, benutze size_t und ptrdiff_t. Zählen Sie nicht auf die Größe von Datentypen: int muss mindestens 16 Bit lang sein, ist fast immer 32 und kann auf einigen Architekturen 64 sein. Gehen Sie nicht davon aus, dass Gleitkommaarithmetik auf verschiedenen Rechnern genauso ausgeführt wird (die IEEE-Standards haben einen gewissen Spielraum).

So gut wie alle Betriebssysteme, die das Netzwerk unterstützen, geben Ihnen einen Weg, mit möglichen Endian-Problemen umzugehen. Benutze sie. Verwenden Sie Sprachfunktionen wie isalpha(), um Zeichen zu klassifizieren, und nicht arithmetische Operationen an Zeichen (was etwas seltsam wie EBCDIC sein könnte). (Natürlich ist es üblicher, wchar_t als Zeichentyp zu verwenden und Unicode intern zu verwenden.)

6

Das letzte Mal, als ich mir die Java-Sprachspezifikation ansah, enthielt sie eine lächerliche Frage im Abschnitt über Ganzzahlboxen.

Integer a = 100; 
Integer b = 100; 

System.out.println(a == b); 

, die drucken true garantiert.

Integer a = 300; 
Integer b = 300; 

System.out.println(a == b); 

Das ist nicht drucken true garantiert. Es hängt von der Laufzeit ab. Die Spezifikation ließ es vollständig offen. Das liegt daran, dass das Boxen eines int zwischen -128 und 127 "interned" -Objekte zurückgibt (analog zur Art, wie String-Literale interniert werden), aber der Implementierer der Language Runtime wird ermutigt, diese Grenze zu erhöhen, wenn sie dies wünschen.

halte ich persönlich, dass als verrückt Entscheidung, und ich hoffe, dass sie es behoben haben, da (write once, run anywhere?)

+0

Sie fanden mehr eine dumme Designentscheidung von Java – GogaRieger

+0

interessant ... Blick in "interned" Objektdetails! Auf einer 1.6.0_14 JVM auf einem Linux x86 32bit System, gibt mir wahr, solange a & b <128 sind. – g06lin

+0

Habe die Größe des Bereichs richtig, aber es ist signiert (-128 bis 127) - siehe http: //java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7 –

0

Mit Java und .NET Sie müssen damit nicht wirklich gestört, es sei denn Du machst sehr low-level Sachen wie Twiddling Bits. Wenn Sie C, C++, Fortran verwenden, könnten Sie vielleicht durchkommen, aber ich würde tatsächlich empfehlen, Dinge wie "stdint.h" zu verwenden, wo Sie definitive Deklarationen wie uint64_t und uint32_t verwenden, um explizit zu sein. Außerdem müssen Sie abhängig von der Art der Verknüpfung bestimmte Bibliotheken erstellen. Beispielsweise kann ein 64-Bit-System gcc in einem Standard-64-Bit-Kompilierungsmodus verwenden.

0

Eine 32-Bit-Maschine ermöglicht Ihnen maximal 4 GB adressierbaren virtuellen Speicher. (In der Praxis ist es sogar weniger als das, normalerweise 2 GB oder 3 GB je nach Betriebssystem und verschiedenen Linker-Optionen.) Auf einem 64-Bit-Rechner können Sie einen großen virtuellen Adressraum haben (in praktischem Sinne nur durch Datenträger begrenzt)) und ein verdammt großer RAM.

Also, wenn Sie erwarten 6GB Datensätze für einige Berechnungen (sagen wir mal etwas, das inkohärenten Zugriff benötigt und kann nicht nur ein wenig nach dem anderen gestreamt werden), auf einer 64-Bit-Architektur könnten Sie es einfach in RAM lesen und Machen Sie Ihre Sachen, während Sie bei einer 32-Bit-Architektur eine grundlegend andere Herangehensweise benötigen, da Sie einfach nicht die Möglichkeit haben, den gesamten Datensatz resident zu halten.

Verwandte Themen