C ist "freier" als Pascal

Für sonstige Unterhaltungen, welche nicht direkt mit Lazarus zu tun haben
Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: C ist "freier" als Pascal

Beitrag von Timm Thaler »

Warf hat geschrieben:Worauf ich hinaus will, der Programmierer sollte niemals Annahmen über eine Programmiersprache aufgrund ihrer Umgebung treffen oder umgekehrt. Wie die Sprachfeatures funktionieren hat den Programmierer nicht zu Interessieren (außer zur performance analyse), und daher können beliebige Konstrukte (natürlich im entsprechenden Kontext) analysiert und miteinander Verglichen werden.


Das ist vielleicht an der Uni so, aber wenn Du mit der Prämisse versuchst Mikrocontroller in C zu programmieren fliegst Du damit hochkant auf die ...

Es gibt im Mikrocontroller-Forum unzählige Beiträge darüber, wieso ein einfaches printf oder ein paar Stringoperatoren den Code explodieren lassen oder den RAM implodieren. Oder wieso eine Ganzzahl-Division eines Bytes durch 2, die ich mit einem Shift erledige, von C unbedingt als 16-bit Software-Division ausgeführt werden möchte, mit entsprechend langer Laufzeit, die dann die PID-Regelung unbrauchbar macht.

Der nächste Schritt ist dann regelmäßig, nach schnelleren Controllern zu schreien oder einen 32-bit ARM zu verwenden, dabei hat der Programmierer nur keine Ahnung, was sein Compiler da anstellt.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: C ist "freier" als Pascal

Beitrag von Warf »

Timm Thaler hat geschrieben:Das ist vielleicht an der Uni so, aber wenn Du mit der Prämisse versuchst Mikrocontroller in C zu programmieren fliegst Du damit hochkant auf die ...

Es gibt im Mikrocontroller-Forum unzählige Beiträge darüber, wieso ein einfaches printf oder ein paar Stringoperatoren den Code explodieren lassen oder den RAM implodieren. Oder wieso eine Ganzzahl-Division eines Bytes durch 2, die ich mit einem Shift erledige, von C unbedingt als 16-bit Software-Division ausgeführt werden möchte, mit entsprechend langer Laufzeit, die dann die PID-Regelung unbrauchbar macht.

Der nächste Schritt ist dann regelmäßig, nach schnelleren Controllern zu schreien oder einen 32-bit ARM zu verwenden, dabei hat der Programmierer nur keine Ahnung, was sein Compiler da anstellt.


Ich zitiere mich mal selbst:
(außer zur performance analyse)

Und alles was du da aufgezählt hast ist Performance Analyse.

Andersrum kann man genauso argumentieren, wer eine WebApp schreibt, und dabei auf die Unterliegende Hardware achtet, und das versucht zu optimieren, der wird nie fertig. Darum habe ich die Performanceanalyse extra rausgelassen, da diese in den meisten Modernen Bereichen ziemlich egal ist.
Zuletzt geändert von Warf am Di 8. Aug 2017, 16:12, insgesamt 1-mal geändert.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: C ist "freier" als Pascal

Beitrag von Timm Thaler »

Warf hat geschrieben:Und alles was du da aufgezählt hast ist Performance Analyse.


Natürlich. Wenn man den Begriff nur weit genug fasst ist alles Performance Analyse. Auch das Hello World.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: C ist "freier" als Pascal

Beitrag von Warf »

Timm Thaler hat geschrieben:Natürlich. Wenn man den Begriff nur weit genug fasst ist alles Performance Analyse. Auch das Hello World.


Warum verwendest du denn den Shift statt der Int Division? Weil sonst das falsche Ergebnis rauskommt, oder um die Performance (Speicher oder Laufzeit) zu verbessern?

Klingt für mich nach Performance Analyse im engst möglichen Sinn.

Wenn das richtige Rauskommt, und die Asymptoptische Laufzeit gleich ist, ist jedwede verbesserung eine Performance Optimierung.

PS: Und Hello World ist genau dann eine Performanceanalyse, wenn man z.B. WriteLn statt einer For Schleife mit Write für jeden char verwendet, da nach jedem Write der Buffer geflusht wird, und daher obwohl das Resultat das selbe ist, WriteLn performanter läuft als Write

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: C ist "freier" als Pascal

Beitrag von Timm Thaler »

Warf hat geschrieben:Warum verwendest du denn den Shift statt der Int Division? Weil sonst das falsche Ergebnis rauskommt, oder um die Performance (Speicher oder Laufzeit) zu verbessern?


Weil ich von Asm komme und da jedes Bit auf dem µC persönlich kenne. Daher fällt mir sowas auf, wenn ich mal in den vom C-Compiler erzeugten Code schaue.

Die Programmierer, die von C am PC auf C am Mikrocontroller kommen, machen sich da aber erstmal keine Gedanken drum. Einen String aufs Display oder an den Uart hast Du am PC im RAM stehen. Wenn Du die gleichen Stringoperatoren auf dem µC verwendest, schreibt der Compiler die Strings auch in den RAM, und dann ist der ganz schnell voll. Deswegen mappt man für feste Strings diese auf den Flash-Speicher. Das ist keine Frage von Perfomance, das ist eine Frage von Sein oder nicht Sein.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: C ist "freier" als Pascal

Beitrag von Warf »

Timm Thaler hat geschrieben:Weil ich von Asm komme und da jedes Bit auf dem µC persönlich kenne. Daher fällt mir sowas auf, wenn ich mal in den vom C-Compiler erzeugten Code schaue.

Die Programmierer, die von C am PC auf C am Mikrocontroller kommen, machen sich da aber erstmal keine Gedanken drum. Einen String aufs Display oder an den Uart hast Du am PC im RAM stehen. Wenn Du die gleichen Stringoperatoren auf dem µC verwendest, schreibt der Compiler die Strings auch in den RAM, und dann ist der ganz schnell voll. Deswegen mappt man für feste Strings diese auf den Flash-Speicher. Das ist keine Frage von Perfomance, das ist eine Frage von Sein oder nicht Sein.


Das was du hier ablieferst ist eine vorbildliche Beschreibung von Performanceanalyse.

Ich versuche das ganze mal anders zu erklären: wenn du einen Rechner hättest der beliebig viel Speicher hat, und beliebig schnell Taktet, würdest du dich dann um diese Änderungen kümmern? Falls nein handelt es sich um Performance Analyse.

Neben der Performanceanalyse gibt es noch die Asymptotische Laufzeit/Speicher Analyse, bei der es darum geht die Laufzeit oder den Speicherverbauch abhängig von der Länge zu reduzieren (z.B. Heapsort braucht n*log(n) Operationen um eine Liste der Länge n zu sortieren, Bubblesort braucht n^2 viele Operationen, somit ist Heapsort Asymptotisch besser). Oder die Programflussanalyse, welche überprüft ob Code Korrekt ist, terminiert, oder unreachable ist.
Jede Änderung machst du ja aus einem bestimmten Grund. Eine Änderung des Programflusses z.B. bei einem Fehler, also wenn dein Code falsche Dinge macht. Du änderst das Asymptotische verhalten aufgrund von Performanceproblemen bei großen Datenmengen (ein Bubblesort auf 10 elementen und ein Heapsort auf 10 elementen macht kaum ein Unterschied, bei 2 Mio Elementen wird es schon interresanter), und die konstante Performance bei Performanceproblemen auf kleinen oder konstanten Daten.

Für den größten Teil der Programmierer (Webentwickler, App entwickler, Handy entwickler) also eigentlich für alle die weder Echtzeitsysteme Schreiben, oder aus der Elektrotechnik (microcontroller, FPGA's, etc.) stammt, ist die Performance analyse praktisch komplett irrelevant, weshalb so gut wie alle Modernen Programmiersprachen das ignorieren. (Aus den Tiobe Index sind in den Top 20 nur C, C++, Pascal, Objective C und ASM die einzigen Sprachen bei denen eine solche Performancanalyse überhaupt Sinn macht)

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: C ist "freier" als Pascal

Beitrag von braunbär »

Warf hat geschrieben:In der kompletten Theoretischen Informatik wird mit 0 Angefangen zu Zählen, das hat verschiedene Gründe, zum einen das wir in der Informatik fast Ausschließlich auf Modulo Arithmetik arbeiten, also auf Mengen von 0 bis p-1 für eine Primzahl p.

Ich habe seinerzeit Informatik studiert. Aber in der täglichen Programmierpraxis mit dem Datentyp array brauchst du keine modulo-Arithmetik, du solltest das nicht mit einer Praktikumsarbeit oder einer Diplomarbeit über irgend ein theoretisches Thema verwechseln. Es würde ja auch nichts dagegen sprechen, dort mit 0 zu zählen zu beginnen, wo es einen Nutzen bietet. Bei normalen arrays kannst du Anfangs- und Endindex frei wählen, warum nicht auch bei offenen Arrays?

Aus Praktischer Sicht hat 0 den großen Vorteil dass jede Zahl mit 0 Multipliziert wieder 0 ergibt, und damit eignet sich das ganze hervorragend für Zeigerarithmetik.

In 99% der Fälle, in denen sie verwendet wird, ist Zeigerarithmetik fehl am Platz. Eine höhere Programmiersprache sollte dem Programmierer die Handhabung von Zeigern generell abnehmen, und kann das in der Regel auch sehr gut. Ausnahmen bestätigen die Regel, wobei aber die meisten Ausnahmen, bei denen Zeigerartithmetik Sinn macht, eher als Hinweis auf fehlende Sprachfeatures anzusehen sind.

Warf hat geschrieben:Und da der einzige Vorteil mit 1 anzufangen ist, das es "natürlicher" ist, dann trainiere ich mir doch lieber an mit 0 anzufangen, und genieße dafür reale Vorteile.

Der Sinn und der reale Vorteil von höheren Programmiersprache liegt darin, Algorithmen aufgabenorientiert formulieren können, möglichst ohne auf Implementierungdetails Rücksicht nehmen zu müssen. Und da würde ich mir eben lieber nicht antrainieren müssen, mit 0 anzufangen. In der Praxis der Anwendungsprogrammierung ist die erzwungen 0-basierte Zählweise in 99% der Fälle von Nachteil, weil der Programmcode die Aufgabenstellung nicht adäquat abbildet, und bietet überhaupt keinen "realen Vorteil".

Timm Thaler hat geschrieben: Oder wieso eine Ganzzahl-Division eines Bytes durch 2, die ich mit einem Shift erledige, von C unbedingt als 16-bit Software-Division ausgeführt werden möchte, mit entsprechend langer Laufzeit, die dann die PID-Regelung unbrauchbar macht.

Das Problem hat ganz sicher nichts mit "Perfomance Analyse" zu tun. Ich würde es aber auch nicht als Schwachpunkt der Sprache C einstufen, sondern als schleißige und ineffiziente Umsetzung der Sprache durch den Compiler. Es steht in der Definition von C sicher nirgends, dass das so umgesetzt werden muss oder soll.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: C ist "freier" als Pascal

Beitrag von Timm Thaler »

braunbär hat geschrieben:Ich habe seinerzeit Informatik studiert. Aber in der täglichen Programmierpraxis mit dem Datentyp array brauchst du keine modulo-Arithmetik, du solltest das nicht mit einer Praktikumsarbeit oder einer Diplomarbeit über irgend ein theoretisches Thema verwechseln.


Ringbuffer für Daten: pos := (pos + 1) mod maxpos;

Passt wunderbar in ein Array 0 bis maxpos - 1. Jetzt mach das mal mit einem Array 1 bis maxpos. Als erstes fliegt Dir das um die Ohren, wenn pos am Anfang noch 0 ist.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: C ist "freier" als Pascal

Beitrag von Warf »

braunbär hat geschrieben:Ich habe seinerzeit Informatik studiert. Aber in der täglichen Programmierpraxis mit dem Datentyp array brauchst du keine modulo-Arithmetik, du solltest das nicht mit einer Praktikumsarbeit oder einer Diplomarbeit über irgend ein theoretisches Thema verwechseln. Es würde ja auch nichts dagegen sprechen, dort mit 0 zu zählen zu beginnen, wo es einen Nutzen bietet. Bei normalen arrays kannst du Anfangs- und Endindex frei wählen, warum nicht auch bei offenen Arrays?


Also ein einfaches Beispiel wo ich vor ein paar Wochen noch Froh war das Arrays bei 0 anfangen: Ich lese Bilddaten in ein Array ein, jeder Wert entspricht einem Voxel. Wobei jede Zeile aus 512 Werten besteht, und jeder Layer aus 512 Zeilen besteht. Um nun einen Index i des arrays in die x, y, z koordinate umrechnen muss, benötige ich Modulo Arithmetik -> 0 basierte Indizes besser. Ich denke, obwohl das ein Uni Praktikum war, das dieses Problem häufiger der Fall ist, auch außerhalb der Uni.

Für so gut wie jedes Verfahren aus der Kryptographie, der Bildverarbeitung, der Datenkommunikation, wird an einer Stelle mindestens Modulo verwendet.

Das ding ist, Arrays mit 1 zu beginnen bringt nun mal gar nichts (außer das es natürlicher ist), und man verliert also auch nichts wenn man mit 0 anfängt. Wenn man allerdings mit 1 anfängt, muss man bei all diesen Modulo Operation geklammert noch +1 hinzufügen. Es ist also ein Trade zwischen keinem Mehraufwand (man hat es nach 1-2 Tagen drauf mit 0 anzufangen), oder viel Mehraufwand. Und um ehrlich zu sein, bei Statischen Arrays verwende ich mittlerweile auch 0 als Startindex, einfach damit ich Konsistent bin. Wenn ich für dynamsiche Arrays den Start Index auch setzen könnte, würde ich dort auch 0 einstellen, einfach weil es mir nichts bringt ihn auf 1 zu setzen.

braunbär hat geschrieben:In 99% der Fälle, in denen sie verwendet wird, ist Zeigerarithmetik fehl am Platz. Eine höhere Programmiersprache sollte dem Programmierer die Handhabung von Zeigern generell abnehmen, und kann das in der Regel auch sehr gut. Ausnahmen bestätigen die Regel, wobei aber die meisten Ausnahmen, bei denen Zeigerartithmetik Sinn macht, eher als Hinweis auf fehlende Sprachfeatures anzusehen sind.


wenn in diesem 1% der Fälle ich mir mit 0 basiertem Index arbeit sparen kann, und in den restlichen 99% der Fälle keine mehraufwand durch 0 Basierte Indizes habe, warum sollte ich dann 1 basierte Indizes verwenden? Da verliere ich ja 1% nutzen

braunbär hat geschrieben:Der Sinn und der reale Vorteil von höheren Programmiersprache liegt darin, Algorithmen aufgabenorientiert formulieren können, möglichst ohne auf Implementierungdetails Rücksicht nehmen zu müssen. Und da würde ich mir eben lieber nicht antrainieren müssen, mit 0 anzufangen. In der Praxis der Anwendungsprogrammierung ist die erzwungen 0-basierte Zählweise in 99% der Fälle von Nachteil, weil der Programmcode die Aufgabenstellung nicht adäquat abbildet, und bietet überhaupt keinen "realen Vorteil".


Um ehrlich zu sein verstehe ich dieses Argument nicht, wenn eine Aufgabe so ins Detail geht, das die Tatsache das ein Array Index mit 0 oder 1 anfängt relevant für die Aufgabenstellung ist, dann ist das wohl eine Aufgabe für Programmieranfänger in ihrer ersten Woche, alle anderen Aufgaben sind meist so gestellt, das sie gar nicht auf die Implementierungsdetails eingehen, und die Tatsächliche Implementierung dem Entwickler komplett allein überlassen (eventuell ein Hinweis wie verwenden sie Arrays, mehr aber auch nicht).

braunbär hat geschrieben:Das Problem hat ganz sicher nichts mit "Perfomance Analyse" zu tun. Ich würde es aber auch nicht als Schwachpunkt der Sprache C einstufen, sondern als schleißige und ineffiziente Umsetzung der Sprache durch den Compiler. Es steht in der Definition von C sicher nirgends, dass das so umgesetzt werden muss oder soll.

Warum hat das nichts mit performanceanalyse zu tun? Wenn ich es richtig verstanden habe ist das Problem: "Die operation funktioniert zwar, braucht aber zu lange". Das ist doch Performance analyse par excellence

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: C ist "freier" als Pascal

Beitrag von braunbär »

Warf hat geschrieben:Also ein einfaches Beispiel wo ich vor ein paar Wochen noch Froh war das Arrays bei 0 anfangen

Die Aussage verstehe ich nicht. Bei statischen arrays kannst du mit 0, 1, oder 27 anfangen, je nachdem, was für die Aufgabenstellung das "natürlichste" ist. Warum müssen dynamische arrays immer bei 0 anfangen? In den Fällen, wo 0 besser ist, würde doch ohnehin nichts dagegen sprechen, 0 zu nehmen, wenn der Anfangsindex frei gewählt werden kann.
Der Nutzen, dass z.B. das Feld Components von 0 bis count-1 geht statt von 1 bis count, erschließt sich mir nicht.

Warf hat geschrieben:bringt nun mal gar nichts (außer das es natürlicher ist),

Das ist ja schon einmal eine ganze Menge. Allein wenn ich mir anschaue, wieviel Zeit in den Foren draufgeht, Programmieranfängern zu erklären, dass sie von 0 bis n-1 zählen müssen statt von 1 bis n wie jeder normale Mensch...
Rechne das hoch auf die Zeit, die dafür insgesamt drauf geht (inkl. Fehlersuche), dass sich Programmierer auf diese in vielen (nicht allen) Fällen unötig kontraintuitive Zählweise einstellen.

Warf hat geschrieben:Und um ehrlich zu sein, bei Statischen Arrays verwende ich mittlerweile auch 0 als Startindex, einfach damit ich Konsistent bin

Verwendest du bei all deinen statischen arrays auch überall die gleiche Obergrenze, um "konsistent" zu sein?
Auf die eigenartige Idee, bei der unteren Feldgrenze von Feldern "konsistent" sein zu wollen, würde man gar nicht kommen, wenn die untere Feldgrenze auch bei offenen Feldern frei wählbar wäre. Das Ist in Wirklichkeit etwa so sinnvoll, wie wenn man zwecks "Konsistenz" alle for-Schleifen immer bei 0 beginnen lassen würde. Nur weil man bei offenen Feldern generell zu dieser verqueren Denke gezwungen wird, fängt man dann am ende bei statischen Feldern auch noch damit an.
Wenn es der Aufgabenstellung entspricht, definiere ich schon auch mal ein array[17..32].
Und wenn ich einen Ringpuffer bilde, dann verwende ich natürlich auch bei einem statischen array 0 als Untergrenze. Das habe ich schon so gehandhabt, lange bevor es dynamische Felder mit dieser unnötigen Einschränkung gegeben hat.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: C ist "freier" als Pascal

Beitrag von Warf »

braunbär hat geschrieben:Die Aussage verstehe ich nicht. Bei statischen arrays kannst du mit 0, 1, oder 27 anfangen, je nachdem, was für die Aufgabenstellung das "natürlichste" ist. Warum müssen dynamische arrays immer bei 0 anfangen? In den Fällen, wo 0 besser ist, würde doch ohnehin nichts dagegen sprechen, 0 zu nehmen, wenn der Anfangsindex frei gewählt werden kann.
Der Nutzen, dass z.B. das Feld Components von 0 bis count-1 geht statt von 1 bis count, erschließt sich mir nicht.

Das ist ja schon einmal eine ganze Menge. Allein wenn ich mir anschaue, wieviel Zeit in den Foren draufgeht, Programmieranfängern zu erklären, dass sie von 0 bis n-1 zählen müssen statt von 1 bis n wie jeder normale Mensch...
Rechne das hoch auf die Zeit, die dafür insgesamt drauf geht (inkl. Fehlersuche), dass sich Programmierer auf diese in vielen (nicht allen) Fällen unötig kontraintuitive Zählweise einstellen.


Na ob es dem Anfänger wirklich schwerer fällt zu begreifen das Arrays mit 0 anfangen, statt dem gewirr wenn du plötzlich einen Array mit 0 basiert, einen mit 1 basiert, und einen mit 17 basiert hat, weil er sich irgendwelche Sources aus dem Internet zusammenkopiert hat, und auf die ganzen Elemente über Magic Numbers zugreift? Das bezweifle ich mal ganz stark. Denn bei sowas hat man sehr schnell einen Speicherüberlauf, und das ist ein Fehler den Anfänger niemals finden.

braunbär hat geschrieben:Verwendest du bei all deinen statischen arrays auch überall die gleiche Obergrenze, um "konsistent" zu sein?
Auf die eigenartige Idee, bei der unteren Feldgrenze von Feldern "konsistent" sein zu wollen, würde man gar nicht kommen, wenn die untere Feldgrenze auch bei offenen Feldern frei wählbar wäre. Das Ist in Wirklichkeit etwa so sinnvoll, wie wenn man zwecks "Konsistenz" alle for-Schleifen immer bei 0 beginnen lassen würde. Nur weil man bei offenen Feldern generell zu dieser verqueren Denke gezwungen wird, fängt man dann am ende bei statischen Feldern auch noch damit an.
Wenn es der Aufgabenstellung entspricht, definiere ich schon auch mal ein array[17..32].
Und wenn ich einen Ringpuffer bilde, dann verwende ich natürlich auch bei einem statischen array 0 als Untergrenze. Das habe ich schon so gehandhabt, lange bevor es dynamische Felder mit dieser unnötigen Einschränkung gegeben hat.


Nein ich verwende keine Feste Obergrenze, da ich dann eine Dynamische Untergrenze bräuchte, und ich öfter von - -> + iteriere als andersrum. Daher würde es keinen Sinn ergeben eine feste Obergrenze zu verwenden.

Ich meine es wäre Praktisch array Grenzen einstellen zu können, aber es wäre gleichzeitig eine Gigantische Fehlerquelle. Hier im Thread haben sich einige Leute über das Break im C Switch aufgeregt, ich behaupte mal, das beliebige Arraygrenzen ein deutlich höheres Fehlerrisiko bergen.

Außerdem kann man ganz einfach überall von 0 hoch Iterieren, und muss nicht die ganze Zeit Low(array) schreiben, was deutlich mehr Aufwand ist (das stört mich schon bei statischen Arrays).

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C ist "freier" als Pascal

Beitrag von Mathias »

Na ob es dem Anfänger wirklich schwerer fällt zu begreifen das Arrays mit 0 anfangen

Wen möglich fange ich auch immer bei 0 an.

So etwas finde ich eine schöne Fehlerquelle. :roll:

Code: Alles auswählen

var
  a:array[-20..-10] of Byte;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: C ist "freier" als Pascal

Beitrag von m.fuchs »

Mathias hat geschrieben:So etwas finde ich eine schöne Fehlerquelle. :roll:

Code: Alles auswählen

var
  a:array[-20..-10] of Byte;

Wo ist denn da die Fehlerquelle?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: C ist "freier" als Pascal

Beitrag von braunbär »

Na ob es dem Anfänger wirklich schwerer fällt zu begreifen das Arrays mit 0 anfangen

Heute noch produziere ich sporadisch run-time-errors, wenn ich nicht aufpasse und von 1 bis n zählen lasse, weil man normalerweise eben so zählt. Es gibt noch ein Leben abseits der Computertastatur, und ich vermute, dass du nicht bei 0 anfängst, wenn du in einem Restaurant die freien Plätze an einem Tisch zählst.

Warf hat geschrieben: statt dem gewirr wenn du plötzlich einen Array mit 0 basiert, einen mit 1 basiert, und einen mit 17 basiert hat,

Weisst du, was ein noch schlimmeres Gewirr ist?
Wenn du plötzlich einen record mit zwei integer und einem real Feld, einen anderen record mit drei byte Feldern und einen dritten record hast, der gar aus zwei Strings besteht.
So was gehört dringend vereinheitlicht!

Man hat nicht "plötzlich" ein array das mit 0 beginnt und eines, das mit 1 beginnt, sondern man verwendet für array die natürlichen Grenzen, die den Daten entsprechen. Beim Durchnumerieren fängt man normalerweise mit 1 an, außer wenn man gute Gründe dafür hat, es anders zu handhaben (z.B bei einem Ringpuffer). Und dann ist der untere Index <> 1 nicht willkürlich oder "Gewirr", sondern ergibt sich ganz selbstverständlich aus der Aufgabenstellung.
Muss das ein Spaß sein, ein array [0..11] für die 12 Monate des Jahres zu definieren, da ist dann jedem auf Anhieb klar, was gemeint ist. Aber da kann ich dann gleich zu C wechseln. :shock:

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: C ist "freier" als Pascal

Beitrag von Warf »

braunbär hat geschrieben:
Na ob es dem Anfänger wirklich schwerer fällt zu begreifen das Arrays mit 0 anfangen

Heute noch produziere ich sporadisch run-time-errors, wenn ich nicht aufpasse und von 1 bis n zählen lasse, weil man normalerweise eben so zählt. Es gibt noch ein Leben abseits der Computertastatur, und ich vermute, dass du nicht bei 0 anfängst, wenn du in einem Restaurant die freien Plätze an einem Tisch zählst.

Warf hat geschrieben: statt dem gewirr wenn du plötzlich einen Array mit 0 basiert, einen mit 1 basiert, und einen mit 17 basiert hat,

Weisst du, was ein noch schlimmeres Gewirr ist?
Wenn du plötzlich einen record mit zwei integer und einem real Feld, einen anderen record mit drei byte Feldern und einen dritten record hast, der gar aus zwei Strings besteht.
So was gehört dringend vereinheitlicht!

Man hat nicht "plötzlich" ein array das mit 0 beginnt und eines, das mit 1 beginnt, sondern man verwendet für array die natürlichen Grenzen, die den Daten entsprechen. Beim Durchnumerieren fängt man normalerweise mit 1 an, außer wenn man gute Gründe dafür hat, es anders zu handhaben (z.B bei einem Ringpuffer). Und dann ist der untere Index <> 1 nicht willkürlich oder "Gewirr", sondern ergibt sich ganz selbstverständlich aus der Aufgabenstellung.
Muss das ein Spaß sein, ein array [0..11] für die 12 Monate des Jahres zu definieren, da ist dann jedem auf Anhieb klar, was gemeint ist. Aber da kann ich dann gleich zu C wechseln. :shock:

Deine erste aussage verstehe ich nicht, wenn ich einen Record mit 2 Strings brauche, dann nützt mir einer mit 3 Bytes gar nichts, warum sollte man da was vereinheitlichen?

Zu den Arrays:

Ein Anfänger hat eine Idee, weiß nicht wie er sie umsetzen soll, googled sich was zu sammeln, copy & paste 3 Sources, und dann hat er plötzlich 3 Arrays. Das Wort plötzlich passt da ziemlich gut. Und natürlich haben Programmierer Gründe die Grenzen zu wählen, ein Anfänger der sich aber nur Sources aus dem Internet kopiert, für den ist der Sinn der Grenzen komplett egal, für den ist da kein Sinn, keine Gründe.

Und dann versucht der Anfänger was zu ändern, kapiert die Array grenzen nicht, baut Müll, und dann landet im nächsten Forum die Frage: "Warum geht das nicht ???!!!??!?!?".

Oder um es mal einfacher zu fassen: Wenn der Index immer mit 0 anfängt, ist in jeder Schleife die durch den Array iteriert die Gefahr für einen Überlauf doppelt so hoch, einmal unten und einmal oben. Wenn man jetzt nur 0 Basierte Arrays macht, ist die Chance einen Überlauf nach unten zu haben deutlich niedriger (da man stumpf nach schema f einfach von 0 hochiterierten muss, und nicht nachdenken muss).

Für erfahrene Nutzer wäre das lediglich eine Spielerei die man zwar nicht braucht, die aber ganz nett sein kann, für Anfänger ist das allerdings eine Falle.

Ein ganz einfaches Beispiel: Ein Anfänger schreibt ein Programm mit solchen Dynamischen Arrays mit angeboren StartIndex, und schreibt diese Funktion:

Code: Alles auswählen

for i := 17 to 17 + Arr.length do
  arr[i]:=i


Jetzt ist er an einer anderen Stelle, muss wieder den Array füllen und denkt sich: Das kenn ich doch schon, da verwende ich einfach die gleiche Funktion, copy & pastet die Funktion, leider wird der Array diesmal mit 1 als Startindex. Der Anfänger denkt darüber nicht nach und kopiert blind die Funktion. Es kommt zu einem Speicherüberlauf und es werden ein paar Daten im Heap überschrieben, aber kein Error geworfen. Plötzlich geht gar nichts mehr. Und niemand weiß warum.

Ich weiß nicht, irgendwie erschließt sich mir einfach kein direkter Vorteil (mir fällt partout auch kein problem ein was ich in den letzen paar Jahren hatte, was mit einem anderen Startindex besser zu lösen wäre). Denn der Nachteil wäre, (wie oben geschildert) grade für Neueinsteiger, gigantisch.

PS: Mir ist es tatsächlich noch nie passiert das ich versucht habe einen Array ab 1 durchzuiterieren, zumindest nicht in den letzten 5 Jahren in denen ich sehr aktiv programmiere.

Antworten