Vor kurzem bin ich auf die Frage gestoßen, wie die Ausgabe von Code vorhergesagt werden kann, bei dem Post / Pre-Inkrement-Operatoren für Ganzzahlen häufig verwendet werden. Ich bin ein erfahrener C-Programmierer, also fühlte ich mich wie zu Hause, aber die Leute machten Aussagen, dass Java das nur blind von C (oder C ++) kopiert hat und dass dies eine nutzlose Funktion in Java ist.
Abgesehen davon kann ich in Java (oder C #) keinen guten Grund dafür finden (insbesondere unter Berücksichtigung des Unterschieds zwischen Post- / Pre-Formularen), da Sie Arrays nicht manipulieren und in Java als Zeichenfolgen verwenden . Außerdem ist es lange her, als ich mich das letzte Mal mit Bytecode befasst habe, daher weiß ich nicht, ob es eine INC
Operation gibt, aber ich sehe keinen Grund dafür
for(int i = 0; i < n; i += 1)
könnte weniger effektiv sein als
for(int i = 0; i < n; i++)
Gibt es einen bestimmten Teil der Sprache, in dem dies wirklich nützlich ist, oder ist dies nur eine Funktion, um C-Programmierer in die Stadt zu bringen?
Antworten:
Es ist sicherlich eine Funktion, "C- (oder C ++) - Programmierer in die Stadt zu bringen", aber die Verwendung des Wortes "nur" hier unterschätzt den Wert einer solchen Ähnlichkeit.
Es erleichtert das Portieren von Code (oder zumindest Codefragmenten) von C (oder C ++) nach Java oder C #
i++
ist weniger zu tippen alsi += 1
undx[i++]=0;
ist viel idiomatischer alsx[i]=0;i+=1;
Und ja, Code, der häufig Post / Pre-Inkrement-Operatoren verwendet, ist möglicherweise schwer zu lesen und zu warten, aber für jeden Code, bei dem diese Operatoren missbraucht werden, würde ich keine drastische Steigerung der Codequalität erwarten, selbst wenn die Sprache diese Operatoren nicht bereitstellen würde. Das liegt daran, dass Entwickler, die sich nicht um die Wartbarkeit kümmern, immer Möglichkeiten finden, schwer verständlichen Code zu schreiben.
Verwandte: Gibt es einen Unterschied zwischen den Java- und C ++ - Operatoren? Aus dieser Antwort kann man schließen, dass jedes genau definierte Operatorverhalten in C in Java ähnlich ist, und Java fügt nur einige Definitionen für die Operatorrangfolge hinzu, wenn C ein undefiniertes Verhalten aufweist. Dies sieht nicht nach Zufall aus, es scheint ziemlich beabsichtigt zu sein.
quelle
x[i++]=0
ist in C idiomatisch, aber ich bin nicht der Meinung, dass es in C # und Java idiomatisch ist. Wie oft stoßen Sie auf solche Phrasen, es sei denn, Sie arbeiten im Bereich Ingenieurwesen / Mathematik, was vermutlich nicht mehr als 1% des Java / C # -Codes in freier Wildbahn ausmacht?Ich verwende manchmal das Postfix-Inkrement in return-Anweisungen. ZB bedenken Sie Folgendes:
Das kann man nicht machen
index += 1
. Zumindest die Postfix-Version kann Ihnen also hin und wieder einige Zeilen ersparen.Diese Bediener sind jedoch in der Tat nicht erforderlich und können die Menschen verwirren. Ich weiß, dass Scala sich gegen diese Betreiber entschieden hat (Sie haben nur
+=
und-=
, wie Sie vorgeschlagen haben), und aufgrund des eher "hochrangigen" Ansatzes vermisse ich sie dort nicht wirklich. Ich hoffe, Java entwickelt sich (langsamer) in die gleiche Richtung.Java hat jedoch eine Reihe anderer Operatoren, die Sie nicht oft "in the wild" sehen (haben Sie jemals verwendet
^=
oder>>>=
?), Und niemand kümmert sich darum.quelle
^=
ist eine ziemlich häufige. Sie können es zum Umdrehen von Bitfeldflags, zum Vertauschen von zwei Ganzzahlen ohne temporäre Variable und in einigen Hash- / Verschlüsselungsalgorithmen verwenden. Ich gebe zu, dass ich nie benutzt habe>>>=
. (Dann wieder habe ich nie benutzt>>>
oder<<<
in jedem Produktionsprogramm ...)Ich habe im Laufe der Jahre viele Sprachen gebaut, hauptsächlich für spezielle Zwecke. Was passiert ist, dass Sie ein großes Publikum haben und alle Erwartungen haben. Bei der Betrachtung jeder Funktion müssen Sie den Nutzen der Funktion gegen die Kosten abwägen, die möglicherweise gegen Erwartungen verstoßen.
Eine, auf die ich persönlich zurücktreten musste, war die Ganzzahldivision, die normalerweise nach unten abschneidet, oder? Wie
3 / 2 = 1.5 = 1
, richtig? Nun, in den frühen Tagen von Fortran hat sich jemand entschieden-3 / 2 = -1.5 = -1
(nicht -2). Mit anderen Worten, wenn die Dividende negativ und der Divisor positiv ist, sollte sie abgeschnitten werden . Beachten Sie, was dies bedeutet - in diesem Fall ist der Rest negativ . Dies verstößt gegen die übliche Annahme, dass Rest = Modul. Wenn Sie Grafiken mit ganzzahligen Koordinaten erstellen, kann dies zu Problemen aller Art führen. SO, habe ich einfach Integer - Division truncate hatte nach unten in der Sprache all die Zeit, und sagen , so in der doc.Und SO, raten Sie mal, was passiert ist? Alles brach los. Die Sprache hatte einen Fehler in der Ganzzahldivision!
Es war nicht gut zu sagen, dass der alte Weg gebrochen war. Es war einfacher, es zu ändern, als es zu argumentieren.
Um Ihre Frage zu beantworten, ist es in Sprachen wie C # und Java einfach einfacher, die ++ - Operatoren (die mir persönlich gefallen) einzuschließen, als zu erklären, warum nicht.
quelle
break
s in jeder Klausel beibehalten , obwohl die Sprache kein Durchfallen zulässt. Während D die Abwärtskompatibilität von C ++ mit C verworfen hat, lautet ihre Richtlinie, dass jedes C-Konstrukt, das D beibehalten hat, einen C-Programmierer so wenig wie möglich überraschen sollte.break; case ...
/
Ausbeutendouble
oderfloat
(double
in Fällen, in denen beides funktionieren würde) und separate Operatoren für die Division mit Boden, abgeschnitten und "was auch immer tun" sowie Modul, Rest und "gleichmäßig teilbar durch" haben "[letzteres ergibt einen Booleschen Wert]. Ich würde davon ausgehen, dass jedes Ergebnis vonint x=y/z;
mit erheblicher Wahrscheinlichkeit von dem abweicht, was beabsichtigt war. Daher sollte der Ausdruck kein Ergebnis liefern .(a+b+c)//3
in den meisten Sprachen geschrieben werden muss, als unangenehmes Durcheinander geschrieben werden muss, um mit der Semantik abgeschnittener Divisionen umzugehen (insbesondere seitdem auf vielen Prozessoren) , eine Etage-Division-durch-drei könnte schneller als eine abgeschnittene gemacht werden!)Ja, es ist an sich nichts Wichtiges, sein einziger Vorteil ist der syntaktische Zucker, der das Tippen erleichtert.
Der Grund, warum es sich in erster Linie um C handelt, liegt allein darin, dass der PDP-11, der früher die Grundlage für C war, eine spezielle Anweisung zum Inkrementieren um 1 hatte. In jenen Tagen war es wichtig, diese Anweisung zu verwenden Holen Sie mehr Geschwindigkeit aus dem System, daher die Sprachfunktion.
Ich denke jedoch, dass die Leute das Kommando so sehr mögen, dass sie sich beschweren würden, wenn es nicht da wäre.
quelle
Dies ist eine idiomatische Syntax in C für viele Situationen (wie die von
for
Ihnen zitierte Schleife). Wie andere bereits gesagt haben, kann sie den Übergang zu Java als neue Sprache erleichtern und das Portieren von bereits vorhandenem Code im C-Stil erleichtern. Aus diesen Gründen war es auch eine natürliche Entscheidung, in den frühen Tagen von Java die Einführung der neuen Sprache zu beschleunigen. Dies ist jetzt weniger sinnvoll, da der kompaktere Code die Programmierer dazu zwingt, Syntax zu erlernen, die nicht unbedingt erforderlich ist.Diejenigen, die es mögen, finden es sowohl bequem als auch natürlich. Es scheint unangenehm, darauf zu verzichten. Die Verwendung gewinnt keine Effizienz, es ist eine Frage der Lesbarkeit. Wenn Sie der Meinung sind, dass Ihre Programme mit diesen Operatoren einfacher zu lesen und zu warten sind, verwenden Sie sie.
Der ursprüngliche Sinn in C war mehr als nur "1 addieren" oder "1 subtrahieren". Es ist viel mehr als nur syntaktischer Zucker oder kleine Leistungssteigerungen. Der Operator in C bedeutet "Inkrementieren (oder Dekrementieren) zum nächsten Element". Wenn Sie einen Zeiger auf etwas haben, das größer als ein Byte ist, und wie in Schritt zur nächsten Adresse
*pointer++
wechseln, kann das tatsächliche Inkrement 4 oder 8 betragen oder was auch immer erforderlich ist. Der Compiler erledigt die Arbeit für Sie, verfolgt die Größe der Datenelemente und überspringt die richtige Anzahl von Bytes:Auf meinem Computer addiert dies 4 zu kpointer, es addiert nicht 1. Dies ist eine echte Hilfe in C, um Fehler zu vermeiden und falsche Aufrufe von sizeof () zu speichern. In Java gibt es keine äquivalente Zeigerarithmetik, daher ist dies keine Überlegung. Dort geht es mehr um die Kraft des Ausdrucks als um alles andere.
quelle