Zum Inhalt springen

warum wird immer bei 0 angefangen zu zählen


Empfohlene Beiträge

Geschrieben
Original geschrieben von nuub

kann mir jeamnd mal sagen warum null? und nich eins? danke

Weil es halt so ist? Warum gab es das Jahr 0 nicht? Warum haben wir die Nase mitten im Gesicht statt zwischen den Beinen? Warum schmeckt mir Cola Light nicht?

Ganz einfach: Es ist so wie es ist.

Gruß,

StarLord

Geschrieben
Original geschrieben von StarLord

Ganz einfach: Es ist so wie es ist.

Naja, nicht ganz.

arrayvar[index] ist ja gleichbedeutend mit *(arrayvar + index). Letztendlich ist die Index-Schreibweise nichts anderes als Zeigerarithmetik mit anschließender Dereferenzierung. Deswegen funktioniert ja auch index[arrayvar].

Um (ohne Indexoperator) auf das erste Element zuzugreifen, schreibt man *(arrayvar), oder auch *(arrayvar + 0), was somit gleichbedeutend mit arrayvar[0] ist.

Geschrieben

In der Antike wurde eine ganze Zeit lang - zumindest im "Westen" - mit 1 angefangen zu zählen. Die 0 mußte erst "erfunden" oder "entdeckt" werden. Wenn ich mich richtig erinnere, waren das arabische Gelehrte, die den "Westen" sowieso mit der "Arithmetik" mathematisch vorwärtsgebracht haben.

Geschrieben

@Klotzkopp:

Ja ja... du must immer deinen Senf dazugeben! ;)

Es ist doch ganz egal ob ein Array nun bei 0 oder bei 1 beginnt. Darum kümmert sich der Compiler! Bei (Visual) Basic fangen Arrays normalerweise mit 1 an (außer man ändert dies ausdrücklich). Bei Ansi C/C++ beginnen sie jedoch (bekanntlich) immer mit 0. Sie hätten es aber damals auch mit 1 oder sogar mit 1000 beginnen lassen können => Es ist einfach so wie es ist. Der Standard wurde so definiert und sicher nicht unbedingt in Anlehnung an die Maschinensprache. Aber ich will mich jetzt wirklich nicht mit dir darum streiten und lasse es nun damit auf sich beruhen.

BTW: Es gibt irgendeine API-Funktion von Microsoft bei der sie irrtümlicherweise mit 1 statt 0 beginnen und es deshalb zu Fehlern kommen kann. Leider fällt mir die Funktion nicht mehr ein.

Gruß,

StarLord

Geschrieben

Computer arbeiten halt Konstruktionsbedingt mit dem Index 0, deshalb ist das eigentlich der Standard. Das Zählen mit 1 ist nur ein Sprachgebrauch aufgrund der Tatsache, daß 1 Apfel 1 mal da ist und er deshalb der 1. sein muß! Dann zählt man in der Reihe: Der erste Apfel ist an Position 1.

Wie gesagt arbeiten Rechner mit der Position 0 weil die Datenleitungen alle auf 0 liegen können. Früher hat man sich dann immer so beholfen, indem man den Index 0 entweder freigelassen hat oder Zugriffe mit Index-1 berechnete um sich dem Sprachgebrauch anzupassen.

Es liegt im Ermessen des Programmierers und Compilerbauers einer Variante den Vorzug zu geben und stellt lediglich ein Schritt auf den Benutzer dar. Da es sich bei C++ um einen Super-Assembler handelt, arbeitet man hier halt mit Index0. Sollten Klassen oder Programme andere Möglichkeiten bieten darf man sich beim Programmierer bedanken und nirgendswo sonst.

Wo kümmert sich da also der Compiler drum??? Ist mir unverständlich. Wenn es sowas wie einen Standard gibt basiert der hier mit Sicherheit auf der Maschinensprache.

Bis heute gilt jedoch:

ES GIBT KEINEN SPRACHÜBERGREIFENDEN EINHEITLICHEN STANDARD FÜR ARRAYS!!!

Geschrieben
Ganz einfach: Es ist so wie es ist.

Wenn schon, dann so:Ganz einfach, weil es im Standard festgeschrieben ist (siehe Abschnitt 8.3.4 im C++ Standard). Aber Klotzkopp hat den Nagel schon auf den Kopf getroffen und auch eine viel anschaulichere Antwort gegeben. Der Compiler versteht array[5] als *(array + 5), was ja bedeutet, daß man 5 auf seine Ursprungsadresse aufaddiert und davon sich den Inhalt geben läßt. Da man aber schon an der ersten Adresse (*array) schon Daten speichern kann und es auch tut, weil man sonst Speicher verschenken würde, ist array[5] das 6. Datum. Aber nicht verwechseln: type array[5] sind hat nur Platz für 5 Daten; nämlich von array[0]..array[4].

Da der Compiler nur *(array + 5) sieht, darf man auch, wie Klotzkopp schon schrieb, auch 5[array] schreiben, weil es für den Compiler *(5 + array) aussieht. Da wir uns in abelschen mathematischen Gebilden befinden, ist 5+array=array+5.

Daß man bei 0 anfängt zu zählen, ist also zum Einen im Standard festgelegt und zum Anderen durch die Vernunft, denn wenn man bei 1 anfangen würde, würde man einen Speicherpaltz verschenken. Natürlich könnte man array[5] als *(array + 5 - 1 ) definieren, aber dann müßte man immer rechnen un das kostet (wenn auch nicht viel) Zeit.

Jan

Geschrieben
Original geschrieben von Orffi

Natürlich könnte man array[5] als *(array + 5 - 1 ) definieren, aber dann müßte man immer rechnen un das kostet (wenn auch nicht viel) Zeit.

Und genau das würde dann der Kompiler machen. So ist es auch bei VB. Euere Definition mit array[5] = *arry+0 - *array+4 ist übrigens auch nicht unbedingt von Bedeutung. Man könnte genauso gut array[5] = *array+1 - *array+5 nehmen und in *array+0 den Typ oder die Länge des Arrays oder sonst irgendetwas anderes definieren. Dann wäre *array+0 z.B 0x00000005L wenn es als BYTE array[5] definiert worden wäre. Das Spielchen "was wäre wenn" kann man unendlich weiterführen... Und ich glaube nicht dass alle Programmiersprachen bei denen Arrays mit 1 beginnen bei der Ausführung oder bei der Compilierung länger brauchen oder einfacher bzw schwerer zu programmierern sind.

Original geschrieben von Crush

Da es sich bei C++ um einen Super-Assembler handelt, arbeitet man hier halt mit Index0.

So ein Blödsinn! Assembler ist keine Hochsprache, und nur weil jemand C++ programmiert kann er noch lange nicht Assembler programmieren. Man merkt mal wieder das ihr zwanghaft versucht C/C++ mit Assembler zu verknüpfen und keine Ahnung von der Systemarchitektur hat. Schon mal auf anderen Systemen programmiert?

Geschrieben

Jede Programmiersprache basiert darauf den Code in ein Assemblerprogramm umzusetzen, weil eben nur in Maschinensprache des jeweiligen Prozessors die Programme tatsächlich laufen können und die Sprache selbst nur ein Abstraktionsmittel ist. Bei C++ und Delphi kann man sich den Assembler-Code der aus dem Programm erzeugt wird sogar direkt abspeichern - ein Indiz dafür ist ja, daß auch Inline-Assembler direkt in den Source eingefügt werden kann (wenn man genau nachdenkt ist das eine logische Schlußfolgerung). Bei anderen Programmiersprachen wird das halt nur nicht als Funktion angeboten aber dennoch durchgeführt - man möchte halt den Programmierer vom echten Code entlasten. Wenn man sich aber die Binaries (.exe, .dll, etc) anschaut entdeckt man was? Auf jeden Fall immer Maschinenprogramme. Irgendwie muß der Sourcode in Assembler umgesetzt werden, sonst hätte man nie ein lauffähiges Programm. (wie war das mit Unwissenheit über Systemarchitekturen?) NACHDENKEN!

Zum Thema Unwissenheit:

"Natürlich könnte man array[5] als *(array + 5 - 1 ) definieren, aber dann müßte man immer rechnen un das kostet (wenn auch nicht viel) Zeit."

-> stimmt nicht ganz, einfach immer vor der Eingabe von dem Zähler 1 abziehen und bei der Ausgabe draufrechnen und das Programm kann den Index unverändert übernehmen: Zeitdifferenz nahezu gegen 0.

"Und ich glaube nicht dass alle Programmiersprachen bei denen Arrays mit 1 beginnen bei der Ausführung oder bei der Compilierung länger brauchen oder einfacher bzw schwerer zu programmierern sind. "

-> war eigentlich nicht das Thema, aber da liegst Du ausnahmsweise mal richtig, zeitlich bekommt man da nicht viel mit und wie schwer oder einfach etwas ist hängt nur davon ab, ob man mit der Syntax der Sprache auch umgehen kann oder sich von der Handhabung mehrerer Programmiersprachen verwirren läßt. Es gibt ja noch anderes als "nur" Arrays (Hash-Arrays z.B.) welche komplizierter zu verstehen und zu handhaben sind, aber eindeutig bei großen Datenmengen und Suchfunktionen wesentlich weiter vorne liegen.

Deine Antwort auf einen meiner Sätze:

"So ein Blödsinn! Assembler ist keine Hochsprache"

-> Hab ich nie behauptet, allerdings ist >jede< Sprache als ein Super-Assembler anzusehen, wenn auch keine die volle Manipulationsfreiheit, wie eben Assembler sie anbietet, eröffnet. (Ausnahme: Inline-ASM) Gegenfrage: Warum ist nur in praktisch jedem Debugger für fast jede Programmiersprache ein Fenster für ASM-Code da???

"und nur weil jemand C++ programmiert kann er noch lange nicht Assembler programmieren."

-> Das ist ja das Schöne an anderen Programmiersprachen: Man muß mit der Realität darunter nicht konfrontiert werden um Ergebnisse zu erlangen. Ich habe nirgendwo behauptet, daß jemand mit C++ auch ASM-Kenntnisse hat, ist auch eher der Ausnahmefall. Auch wenn sich alle dagegen wehren: Ist eben die Sprache der Maschinen - da wird man mit leben müssen, auch wenn man sie selber nicht beherrscht oder sich was anderes wünscht. Es wurde wohl schon mal der Schritt in Codemorphing, usw. ausprobiert, aber es wird wohl nie einen "echten" Java oder C++-Prozessor geben - und wenn ist nach "unten" hin wieder ein runterbrechen des Befehlssatzes auf Microcodes notwendig. Auch die X86-Prozessoren machen das sogar wenn man´s genau nimmt - sonst würden die Chiphersteller mit der Technik einen ewigen Rechtsstreit führen. Also ist die echte Maschinensprache theoretisch auch noch nicht das gelbe vom Ei, sondern der jeweils verwendete interne Microcode in den Prozessoren.

"Man merkt mal wieder das ihr zwanghaft versucht C/C++ mit Assembler zu verknüpfen und keine Ahnung von der Systemarchitektur hat." (habt wenn schon oder wolltest Du mich damit persönlich ansprechen?)

-> ??? Soll ich Dir mal Nachhilfe geben ??? Hört sich für mich etwas wie Neid an, aber ich habe von Chiptechnologie und Assembler-Programmierung auf mehreren Prozessoren etwas mehr Ahnung als der Durchschnitt. Was Systemarchitektur und Compilerbau betrifft glaube ich auch nicht hinterm Mond zu leben. Und wenn man eine technische Frage stellt versuche ich jedenfalls, soweit möglich wie hier, sie auch technisch zu beantworten - auch wenn es aus anderer Betrachtungsweise ja eine wilkürliche Entscheidung des Compilerbauers sein kann wie ich ja auch einräume. Es gibt mehrere Möglichkeiten herauszufinden, daß die Erde rund ist: Vielfalt ist lebensqualität! Ob das einem nun paßt oder nicht.

"Schon mal auf anderen Systemen programmiert?"

-> Ja! Und? Was willst Du mir damit sagen?

Abschließend will ich noch anfügen, daß Assembler auch nur Mnemonics sind, also wieder eine Bezeichnung und ausgedachte Schreibweise um die tatsächliche Bitpfriemelei vorm Programmierer zu "verstecken". Aber was Systemnaheres gibt es halt einfach nicht. Sehr wohl gibt es aber auch (meist Co- oder Matrix-)Prozessoren, die nicht einer Standard-Sprache herkömmlicher CPUs entsprechen. Sei es bei diversen DSPs, Grafikchips (Blittern) oder sonstwas - aber auch hier erlaubt man sich schleunigst eine Art Befehlssatz zusammenzustellen, damit man die Befehle nicht einzeln aus Nullen und Einsen zusammensetzen muß. Aber eines haben die alle gemeinsam: Deren Indizes beginnen IMMER bei 0. (wieso nur, wenn es mit der Architektur nichts zu tun hat?)

Geschrieben

Ich finde, ihr redet an dem Problem vorbei. Die Frage ist doch, warum fängt man bei 0 an zu Zählen !?!

Und um das zu begründen müßte man in die "Tiefe der Zeit" hinabsteigen, und sich fragen, ab wann und warum angefangen worden ist, mit 0 zu zählen.

Mir fehlt der historische Kontext. Da die Frage *sehr allgemein* gestellt worden ist, müßte doch eigentlich ein Hinweis darauf gebracht werden.

Ich bezweifle, daß Lochkartenmaschinen in Assembler, C, oder C doppelplus programmiert werden konnte...

Andererseits basiert *eine Menge* auf den Konzepten der Lochkartenmaschinen...

Insofern geht die Diskussion um Arrays und Superassembler eigentlich an der Frage vorbei.

Geschrieben

@Alrik Fassbauer

Ich bezweifle, daß Lochkartenmaschinen in Assembler, C, oder C doppelplus programmiert werden konnte...

Wenn du mit Lochkartenmaschinen Computer (Mainframes) meinst die mittels Lochkarten programmiert wurden, dann konnte man diese ausser mit ASSEMBLER auch noch mit den höheren Programmiersprachen FORTRAN, ALGOL, LISP, COBOL, C, PASCAL, PROLOG, PL/1 usw. programmieren.

Manne :cool:

Geschrieben
Und genau das würde dann der Kompiler machen.

Aha, was der Compiler nicht alles so macht. Das müßt ihr mir dann schon mal erklären, wie er Berechnungen zur Compilezeit durchführt, die er aber erst zur Laufzeit durchführen kann. Wenn ich nämlich ein dynamisches Array habe, dann kann ich doch noch nicht zur Compilezeit wissen, von welchem Wert ich 1 abziehen soll.

Man könnte genauso gut array[5] = *array+1 - *array+5 nehmen und in *array+0

Es fehlen die Klammern.... *(array+1) ist das 2 Element im Array, *array+1 ist das erste Element im array plus 1 (array[0]+1).

Zum Thema Unwissenheit:

"Natürlich könnte man array[5] als *(array + 5 - 1 ) definieren, aber dann müßte man immer rechnen un das kostet (wenn auch nicht viel) Zeit."

-> stimmt nicht ganz, einfach immer vor der Eingabe von dem Zähler 1 abziehen und bei der Ausgabe draufrechnen und das Programm kann den Index unverändert übernehmen: Zeitdifferenz nahezu gegen 0.

Ich frage mich ja ehrlich ob Du den Unterschied zwischen 0 und nahezu gegen 0 kennst? Ich persönlcih sehe nämlich keinen Unterschied zwischen "kostet ein bißchen Zeit" und kostet Zeit die nahezu gegen 0 geht.

Ich finde, ihr redet an dem Problem vorbei. Die Frage ist doch, warum fängt man bei 0 an zu Zählen !?!

Und um das zu begründen müßte man in die "Tiefe der Zeit" hinabsteigen, und sich fragen, ab wann und warum angefangen worden ist, mit 0 zu zählen.

Natürlich konnte man erst bei 0 anfangen zu zählen, als diese "entdeckt" worden ist. Aber auch heute wird nicht generell bei 0 angefangen zu Zählen. Viele definieren die natürlichen Zahlen so: N={1,2,3...} (und es liegt sicherlich nicht daran, daß sie die 0 nicht kennen). Die Diskussion geht also schon in die richtige Richtung.

Jan

Geschrieben

"Ich frage mich ja ehrlich ob Du den Unterschied zwischen 0 und nahezu gegen 0 kennst? Ich persönlcih sehe nämlich keinen Unterschied zwischen "kostet ein bißchen Zeit" und kostet Zeit die nahezu gegen 0 geht. "

-> Beim PentiumPro war´s ein Vierttel CPU-Takt (wegen dem runterbechen auf Mikro-Ops) - und die K7-serien mit DirectPath sind noch schneller (hab nur keine Clocking-Tabelle für). Macht bei 1Ghz heut´ maximal 0,00000000025 Sekunden was für mich so ungefähr gegen 0 geht. =8-)

Geschrieben
Original geschrieben von nuub

kann mir jeamnd mal sagen warum null? und nich eins? danke

Soweit ich weiß, rechneten die ersten Maschinen (Turing lässt grüssen) im Binärsystem. Hier gibt es nur 0 und 1 (aus und an).

Um alle unsere natürlichen Zahlen darstellen zu können nimmt man zum Rechnen das Dezimalsystem. Das geht von 0-9, da 10 ja schon wieder 2 Dezimalstellen besitzt.

Deswegen wird bei 0 angefangen und nicht bei 1, ansonsten hättest du ja das nonale System.

So einfach isses. Und auch schon die alten Griechen kannten die 0.

Gruß,

Dana

Geschrieben

@Crush

Du vergißt eine Kleinigkeit: In den 70er Jahren gab es noch keinen Pentium Pro. Also dauerte "damals" die Rechnung auch länger und deshalb machte es aus der Sicht von "damals" auch Sinn, auf die "Rechnung" -1 zu verzeichten.

Wobei ich dabei bleibe, daß 0,00000000025 immer noch nicht 0 ist und nicht jeder hat einen 1GHz Rechner zu Hause 'rumfliegen.

Jan

Geschrieben

Laß Deine alte Kiste nur 100 Mhz haben und trotzdem geht das so schnell, daß Du das -1 nieeeee irgendwann wahrnehmen kannst. Also meiner Meinung nach ist diese Mikroskopisch kleine Zeit nicht erwähnenswert, selbst wenn ich auf 100.000 Felder hintereinander zugreife, und wenn man irgendwann etwas merkt, dann nur weil der Zugriff selbst unvergleichlich viel länger dauert als der Substraktionsbefehl. Selbst auf meinem alten C64 konnte ich diese Zeitspanne nicht mal annähernd erfühlen - und da hat der noch mehrere Taktzyklen von 1 Mhz gebraucht - und das liegt jetzt auch schon 20 Jahre zurück (weit genug?).

Zeit ist relativ und wird von jedem Individuum anders wahrgenommen. Hab ja nicht behauptet, daß das gleich 0 ist, sondern "nahezu gegen 0" was meinem Verständnis nach noch nicht ganz null entspricht - aber es lohnt sich ja nicht, sich da drüber die Haare zu raufen.

Beugen wir uns einfach der Macht der Programmiersprachen und wenden sie so an wie es uns von ihnen vorgeschrieben wird ohne die Hintergründe zu erfragen - wollen ja viele auch gar nicht, daß man sooo tiefe Einblicke erhält.

:marine

Geschrieben

Also meiner Meinung nach ist diese Mikroskopisch kleine Zeit nicht erwähnenswert...

Der Punkt ist aber der, daß man mit einer Rechnung -1 definitiv länger braucht als ohne.

Ob Du das dann erfühlen kannst, oder nicht ist ziemlich egal. Vermutlich wird es sich in der Praxis nicht bemerkbar machen, aber deswegen sollte man nicht so tun, als gäbe es keinen Unterschied.

Etwas anderes hatte Orffi auch nie gesagt - er schreibt im Originalstatement ja auch

...das kostet (wenn auch nicht viel) Zeit

Die Frage war eben, warum man mit 0 anfängt und nicht mit der 1. Die Antwort liegt unter anderem darin begründet, daß beim Beginn mit der 0 die Speicher-Adressierung effizienter ist.

Eine weitere Begründung wären entsprechend festgelegte Standards.

Zeit ist relativ und wird von jedem Individuum anders wahrgenommen.

Erzähl das mal bei einem Code-Review, wenn dein Code im Profiling langsam ist :) - Aber im Ernst: egal, wie die (Lauf-)Zeit wahrgenommen wird, so sollte man sich eben schon um eine möglichst effiziente Implementierung bemühen.

Wenn man zwei Algorithmen hat, die das gleiche Resultat liefern, der eine aber eine Rechenoperation mehr benötigt, dann wird man wohl stets den Algorithmus ohne die zusätzliche Operation nehmen.

Und zwar auch dann, wenn beide in der Praxis gleich schnell laufen.

Beugen wir uns einfach der Macht der Programmiersprachen und wenden sie so an wie es uns von ihnen vorgeschrieben wird ohne die Hintergründe zu erfragen...

Aber genau um die Hintergründe geht es doch hier. Wenn Dich das nicht interessiert, ok -- andere möchten eben auch gerne wissen, was sie tun und nicht einfach nur Programmiersprachen "blind" anwenden.

Evil

Geschrieben

Bei solchen philosophischen Fragen spielt es eh keine Rolle was man sagt, weil jeder einen anderen Standpunkt vertritt und die Wahrheit meist dazwischen liegt. Was zu diesem Thema gesagt werden konnte ist wohl größtenteils schon gesagt worden und da darf muß sich jeder nun sein Körnchen selbst rauspicken. Falsch war eigentlich fast nichts, aber wie man sieht gehen die Gemüter selbst bei so trivialen Fragen weit auseinander. Ich jedenfalls habe eingeräumt, daß es mehrere Sichtweisen gibt und die Theoretischen wie die Praktischen angesprochen. Diese Diskussion wird nämlich so niemals ein Ende finden - weil es eben keine 100-Punkte-Antwort auf diese Frage gibt!

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...