C Eigenarten

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.

C Eigenarten

Beitragvon pluto » 14. Jan 2019, 15:22 C Eigenarten

Hallo

Wir hatten letzten im Verein ein Arduino C Code geschrieben, der schon recht komplex war... ich selbst habe ihn diesmal nicht geschrieben....

Der der, diesen Code geschrieben hat, hat ein Kleinigkeit vergessen, kann passieren. Der C-Compiler hat sich aber NICHT drüber beschwert.

Erst als wir die Ausführlichen Fehlermeldungen Eingeschaltet hatten und auch über alle Warnungen Informiert werden wollten, war es schnell klar, was vergessen wurde, haltet euch fest:
In einem switch case wurde case Vergessen...

Angeblich soll in C++ sogar möglich sein, case vor dem switch zu Nutzen....

Ich frage mich immer wieder, je mehr ich zwischendurch C Verwende, warum C zu einer "Welt" Sprache wurde, ob wohl viele Fehler, Für den Compiler keine Fehler sind.
In jeder anderen Sprache hätte der Compiler gemeckert...
MFG
Michael Springwald
Aktuelles Projekt: PlutoArduino
pluto
 
Beiträge: 6827
Registriert: 19. Nov 2006, 12:06
Wohnort: Oldenburg/Oldenburg
OS, Lazarus, FPC: Linux Mint 18.3 | 
CPU-Target: AMD
Nach oben

Beitragvon Warf » 14. Jan 2019, 15:53 Re: C Eigenarten

Erst als wir die Ausführlichen Fehlermeldungen Eingeschaltet hatten und auch über alle Warnungen Informiert werden wollten, war es schnell klar, was vergessen wurde, haltet euch fest:
In einem switch case wurde case Vergessen...

Dashalb ist das erste was man als C(++) Entwickler machen sollte wenn man ein neues Projekt erstellt die Kompiler Flags -Wall (alle Warnings) und -Wpedantic (code quality warnings) anzuschalten. Es ist zwar nicht die Default Einstellung des Compilers, aber es gibt kaum ernsthafte C++ programmierer die ohne diese Flags arbeiten. Ich gehe sogar meist noch einen schritt weiter und verwende -Werror (warnings werden zu errors) damit ich nicht ausversehen warnings übersehe.

In einem switch case wurde case Vergessen...

Meinst du
Code: Alles auswählen
switch (something) {
  Value:
// statt
  case Value:
}

Das ergibt auch sinn, da ohne das case ists ein goto label. Beides ist syntaktisch korrekt, warum sollte der Compiler also meckern?

Ich frage mich immer wieder, je mehr ich zwischendurch C Verwende, warum C zu einer "Welt" Sprache wurde, ob wohl viele Fehler, Für den Compiler keine Fehler sind.
In jeder anderen Sprache hätte der Compiler gemeckert...

C ist als Sprache für Betriebsysteme entwickelt worden und unter dieser Prämisse macht es auch sinn. Ein switch case ist eine Sprungtabelle in C, die cases sind also wie goto labels. Grade für Betriebsysteme beitet das ne menge Vorteile. Hier mal ein Beispiel:
Code: Alles auswählen
switch (someInt) {
case 0:
  do something;
case 1:
  somethingelse;
  break;
case 2:
  some other stuff;
  break;
default:
  defaultstuff;
}

intern macht der Compiler das draus:
Code: Alles auswählen
  const void* table[] = {&&c_1 ,&&c_2, &&c_3}
  if (someInt > 2) goto c_default;
  table[someInt](); // rufe den funktionspointer aus der jumping table auf
c_1: // goto lable für case 0
  do something;
c_2: // goto label für case 1
  somethingelse;
  goto c_end; // break
c_3: // goto label für case 2
  some other stuff;
  goto c_end; // break
c_default:
  defaultstuff;
c_end: // end of switch


Zum einen ist das natürlich viel effizienter als viele ifs, und wenn man darüber bescheid weiß ist das switch case statement eins der mächtigsten tools für entwickler. Was z.B. auch geht:
Code: Alles auswählen
switch (someInt) {
case 0:
  Initialize;
case 1:
case 2:
case 3:
  some code;
  break;
}

Wenn someInt 0 ist wird also initialize und some code; ausgeführt, wenn someInt 1,2 oder 3 ist wird nur some code ausgeführt. Das man ein case vor dem Switch schreiben kann ist mir neu. Wenn ist das eine eigenheit eines bestimmten compilers, gehört aber garantiert nicht in den Standard.

C++ erbt alle eigenheiten von C, was zum einen C++'es größter Fluch wie auch größter Segen ist.

Ich finde das sind nichtmal die probleme von C/C++, das sind eigenheiten die man kennen muss, aber wenn man sie verstanden hat macht das alles im groben und ganzen auch sinn. Die probleme fangen wo ganz anders an, um mal 3 zu nennen:
1. C strings. Welcher idiot kam auf die Idee 0 terminierte Strings zu verwenden? Pascal hat es von Anfang an richtig gemacht, jede andere Sprache (selbst C++) macht es auch so (also String besteht aus Längen feld und Char array). Auf 8 Bit systemen ist der Speicherverbrauch von 0 terminierten strings und short strings gleich, auf allen anderen systemen wird maximal sizeof(intptr) - 1 mehr bytes benötigt, dafür verbietet C einfach die verwendung eines zeichens komplett in strings.
2. Undefined behaviour: wenn was dem standard nicht entspricht ists den compilerbauern überlassen was passiert. Somit kann G++, Vc++ oder intel C++ mit dem selben code unterschiedliche Semantik erzeugen
3. Compiler spezielles Behaviour: oben verwende ich den && operator um die addresse eines goto labels zu bekommen, das funktioniert aber nur bei gcc. Genauso wenn man ein packed objekt haben will ist geht das unter gcc glaube ich mit __packed__, ist aber auch gcc speziell, für die anderen compiler keine ahnung.
Warf
 
Beiträge: 1047
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon pluto » 14. Jan 2019, 16:15 Re: C Eigenarten

CODE: ALLES AUSWÄHLEN
switch (something) {
Value:
// statt
case Value:
}
Das ergibt auch sinn, da ohne das case ists ein goto label. Beides ist syntaktisch korrekt, warum sollte der Compiler also meckern?

Genau, dass meine ich, dass ist das Problem... warum soll der Compiler bei einem if(test = 1) meckern... wobei das ja eher eine zuweisung ist...
es mag Syntaktisch richtig sein, aber das Label "Value" gibt es ja nirgends....

Zum einen ist das natürlich viel effizienter als viele ifs, und wenn man darüber bescheid weiß ist das switch case statement eins der mächtigsten tools für entwickler

Stimmt. was mich wundert ist immer das "break"... weil auch in deinem zweiten Beispiel, ist der Block doch schon zu ende
Code: Alles auswählen
c_1: // goto lable für case 0
  do something;
c_2: // goto label für case 1
  somethingelse;
  goto c_end; // break
 

Hier ist die Frage, warum er bei C_2 weiter macht, ohne das break bzw. warum C-2 ein goto Label für case ist.. das würde vielleicht auch das break erklären, was man ja setzten muss....

Wenn someInt 0 ist wird also initialize und some code; ausgeführt, wenn someInt 1,2 oder 3 ist wird nur some code ausgeführt. Das man ein case vor dem Switch schreiben kann ist mir neu. Wenn ist das eine eigenheit eines bestimmten compilers, gehört aber garantiert nicht in den Standard.

Ob das zum standard gehört weiß ich nicht, jedenfalls soll das bei C++ so sein.... bei C/C++ könnte ich mir auch gut vorstellen, dass es zum Standard gehört, aber wozu?

Ich finde das sind nichtmal die probleme von C/C++, das sind eigenheiten die man kennen muss, aber wenn man sie verstanden hat macht das alles im groben und ganzen auch sinn. Die probleme fangen wo ganz anders an

Richtig. Der Punkt ist: Jeder der C Programmiert ob jetzt Beruflich oder Privat, wird früher oder Später drüber stolpern. Es gibt auch hier Beispiele, dass diese Fehler auch Experten zum Verhängnis werden, leider finde ich den Artikel gerade im Internet nicht wieder, wo eine Rakte Explodiert ist oder gesprengt werden musste weil = und == vertauscht wurden...

Die probleme fangen wo ganz anders an, um mal 3 zu nennen:

Und dann wird so eine Sprache für ein Betriebssystem Verwendet...

Ich denke, es gibt bestimmt noch mehr Eigenarten, die nicht alle bekannt sind egal wie lange man jetzt in c oder c++ programmiert hat... in pascal wird es auch Eigenarten geben z.b. Zirkulärer Unit Aufruf.... in vielen Sprachen ist das kein Problem, in Pascal schon....
MFG
Michael Springwald
Aktuelles Projekt: PlutoArduino
pluto
 
Beiträge: 6827
Registriert: 19. Nov 2006, 12:06
Wohnort: Oldenburg/Oldenburg
OS, Lazarus, FPC: Linux Mint 18.3 | 
CPU-Target: AMD
Nach oben

Beitragvon Warf » 14. Jan 2019, 16:32 Re: C Eigenarten

pluto hat geschrieben:Genau, dass meine ich, dass ist das Problem... warum soll der Compiler bei einem if(test = 1) meckern... wobei das ja eher eine zuweisung ist...
es mag Syntaktisch richtig sein, aber das Label "Value" gibt es ja nirgends....

Du denkst zu pascal artig, in C musst du labels nicht definieren, sobald irgendwo im quelltext "Label:" steht, exsistiert dieses goto label und man kann hinspringen, ob du es tust oder nicht ist deine Sache. Mit -Wall sollte der Compiler dich allerdings auf unbenutzte Labels hinweisen (weshalb man immer Wall verwenden sollte). Da C für betriebsysteme entwickelt wurde die aus performance gründen sehr viel goto verwenden, wollte man einfach nicht immer wie in pascal hochscrollen müssen und labels expliziet wie variablen definieren müssen. Was können die C entwickler denn dafür das goto aus der mode gekommen ist, oder das nicht Betriebsystementwickler C benutzen wollen :mrgreen:

Stimmt. was mich wundert ist immer das "break"... weil auch in deinem zweiten Beispiel, ist der Block doch schon zu ende

Hier ist die Frage, warum er bei C_2 weiter macht, ohne das break bzw. warum C-2 ein goto Label für case ist.. das würde vielleicht auch das break erklären, was man ja setzten muss....

Du musst break nicht setzen, das ist die falsche denkweise, du musst es so sehen, in einem switch springt der Computer zu dem Case label und fängt von da aus an von oben nach unten jede zeile auszuführen. Ein break in einem Switch wiederum ist dann der befehl: Spring aus diesen Switch raus. Es gibt sehr viele fälle da will man grade kein break haben, weil man den hinteren teil so oder so ausführen will, und die frage ist wie viel vom oberen teil man überspringen möchte. Grade wenn man Simulatoren/Interpreter für Sprachen/alte Prozessoren schreibt ist das etwas was man sehr oft machen will und muss, und dafür ist C auch toll (In pascal würde ich dafür goto rausholen, da ist mir C's switch doch lieber)

Richtig. Der Punkt ist: Jeder der C Programmiert ob jetzt Beruflich oder Privat, wird früher oder Später drüber stolpern. Es gibt auch hier Beispiele, dass diese Fehler auch Experten zum Verhängnis werden, leider finde ich den Artikel gerade im Internet nicht wieder, wo eine Rakte Explodiert ist oder gesprengt werden musste weil = und == vertauscht wurden...


Ein großteil wird durch Warnings vermieden, z.B. = und == in einem if, da fragt dich der Compiler bei Wall ob du das auch wirklich willst (um die warning weg zu bekommen muss man dann nochmal extra separat klammern). Es ist kein Hexenwerk C zu verstehen, es ist nur super unintuitiv

Und dann wird so eine Sprache für ein Betriebssystem Verwendet...

Na wenn du ein betriebsystem schreibst kennst du deinen Compiler normalerweise in und auswendig, mit allen querks und Eigenheiten (womöglich benutzt du sogar einen selbst geschriebenen compiler), von der seite aus ist das für diese leute wahrscheinlich so natürlich wie für dich als Pascal programmierer vor die Typen ein T zu schreiben. Problematisch wirds erst wenn der normale Teilzeitprogrammierer plötzlich von Java, Pascal o.ä. zu C wechselt und erst mal keine ahnung hat was abgeht.

Ich denke, es gibt bestimmt noch mehr Eigenarten, die nicht alle bekannt sind egal wie lange man jetzt in c oder c++ programmiert hat... in pascal wird es auch Eigenarten geben z.b. Zirkulärer Unit Aufruf.... in vielen Sprachen ist das kein Problem, in Pascal schon....

Ich sag nur
Code: Alles auswählen
procedure Foo();
const Bar: Integer = 0;
begin
  WriteLn(Bar);
  Inc(Bar);
end;

als ich das zum ersten mal gesehen hab hatte ich keine ahnung was da abgeht.



Ich selbst arbeite aktuell an einem Programm was sehr performance abbhängig ist, und da ist C++ die Sprache der Wahl, all diese kleinen Querks und Eigenheiten bieten für dieses Projekt massive Vorteile, die ich nicht missen will. Hingegen bei den Standard GUI Programmen die ich mit Lazarus schreibe, da bräuchte ich den ganzen kram nicht. Und auch für Mikrokontroller (da du ja durchn arduino drauf gekommen bist) ist C++ toll, da ich da genau sehen kann wie effizient ich programmiert hab, denn bei nur 4k ram und 16 mhz merk man richtige unterschiede wenn man was ineffizient implementiert
Warf
 
Beiträge: 1047
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon pluto » 14. Jan 2019, 17:15 Re: C Eigenarten

Du denkst zu pascal artig, in C musst du labels nicht definieren, sobald irgendwo im quelltext "Label:" steht, exsistiert dieses goto label und man kann hinspringen,

ja, vielleicht ist der Fehler, ich kann aber doch, da nicht hinspringen, wenn ich gar nicht weiß wo es steht?

Du musst break nicht setzen, das ist die falsche denkweise, du musst es so sehen, in einem switch springt der Computer zu dem Case label und fängt von da aus an von oben nach unten jede zeile auszuführen. Ein break in einem Switch wiederum ist dann der befehl: Spring aus diesen Switch raus.

Aber wenn der case "zu ende" ist, müsste doch Automatisch Schluss sein?

Ein großteil wird durch Warnings vermieden, z.B. = und == in einem if, da fragt dich der Compiler bei Wall ob du das auch wirklich willst (um die warning weg zu bekommen muss man dann nochmal extra separat klammern). Es ist kein Hexenwerk C zu verstehen, es ist nur super unintuitiv

Ja, C ist einfach... dann liegt es wohl daran, dass der Compiler einfach nicht drauf hinweist, bei den Standard Einstellungen.

als ich das zum ersten mal gesehen hab hatte ich keine ahnung was da abgeht.

Das sollte doch nicht gehen? Bar ist doch ein const?

Hingegen bei den Standard GUI Programmen die ich mit Lazarus schreibe, da bräuchte ich den ganzen kram nicht. Und auch für Mikrokontroller (da du ja durchn arduino drauf gekommen bist) ist C++ toll

Eigentlich solltem an auch hier Rust verwenden, für AVR gibt es noch keine Unterstützung, aber für STM32.... darum verwende ich auch Lieber C++...

da ich da genau sehen kann wie effizient ich programmiert hab, denn bei nur 4k ram und 16 mhz merk man richtige unterschiede wenn man was ineffizient implementiert

Ja.... Bei einem ESP muss ich nicht so genau drauf achten, aber bei einem atMega328 oder einem attiny84 schon deutlich mehr...
Wobei meine Programme meistens nicht an die Grenzen gehen... nur selten...
MFG
Michael Springwald
Aktuelles Projekt: PlutoArduino
pluto
 
Beiträge: 6827
Registriert: 19. Nov 2006, 12:06
Wohnort: Oldenburg/Oldenburg
OS, Lazarus, FPC: Linux Mint 18.3 | 
CPU-Target: AMD
Nach oben

Beitragvon kupferstecher » 14. Jan 2019, 17:58 Re: C Eigenarten

Warf hat geschrieben:C ist als Sprache für Betriebsysteme entwickelt worden und unter dieser Prämisse macht es auch sinn.

Bei der Betriebssystemprogrammierung müsste man eigentlich "konservativer" sein, d.h. Pascalsche Typsicherheit seh ich eher als Argument für Betriebssystemprogrammierung. Ich kenn mich mit C nicht so gut aus, auch ist der Erfolg schon vor meiner Zeit eingetreten. Meine Vermutung ist aber, dass C so erfolgreich ist, weil es durch seine Universalität bei vergleichsweise niedriger Implementierungstiefe sehr viele Möglichkeiten bietet. Das vereinfacht die Compilerentwicklung, bzw. bei gleichem Aufwand ist die Erstellung eines ausgefuchsteren Kompilers möglich, z.B. im Bereich Optimierungen. Du sagst ja, dass du aus Performancegründen auf C++ setzt. Der Performacevorteil ist aber nicht in der Sprache begründet, aus Pascal-Quellcode könnte das gleiche Binary erzeugt werden. Sondern die vorhandenen Compiler sind halt ausgefuchster. Was zum einen an der Marktposition liegt, aber zum anderen eben auch an der Sprache.
kupferstecher
 
Beiträge: 172
Registriert: 17. Nov 2016, 11:52

Beitragvon pluto » 14. Jan 2019, 18:30 Re: C Eigenarten

Bei der Betriebssystemprogrammierung müsste man eigentlich "konservativer" sein, d.h. Pascalsche Typsicherheit seh ich eher als Argument für Betriebssystemprogrammierung.

Nicht nur das.
Was ist mit dem beliebten Buffer Überlauf?

n. Meine Vermutung ist aber, dass C so erfolgreich ist, weil es durch seine Universalität bei vergleichsweise niedriger Implementierungstiefe sehr viele Möglichkeiten bietet

"Ich habe gehört" C hat einen sehr guten Optimierer.... Das ist einer der Gründe warum es so erfolgreich sein soll...
Ob das Stimmt kann ich selbst nicht nachprüfen...
Außerdem gibt es sehr viele Konzepte in C die ist in Pascal nicht so gibt... z.b. Templates oder so ähnlich... NameSpace oder so ähnlich....
Ob die Vorteile bringen weiß ich nicht...

Du sagst ja, dass du aus Performancegründen auf C++ setzt. Der Performacevorteil ist aber nicht in der Sprache begründet, aus Pascal-Quellcode könnte das gleiche Binary erzeugt werden

Nein.... Die C Binary sind deutlich kleiner als die Pascal Binary auch das kann ich nicht beweisen....
Außer: Ich habe ein Pascal Programm kompiliert für ein AVR und ein ähnliches für Arduino C es ging um ein einfaches Blink Beispiel..
Das Pascal Programm war größer... auch wenn nicht extrem....

ondern die vorhandenen Compiler sind halt ausgefuchster. Was zum einen an der Marktposition liegt, aber zum anderen eben auch an der Sprache.

Ja... Bei Rust ist das Problem derzeit, dass sich das Radikal ändern kann, die Sprache, die Konzepte, der Compiler...
Es soll wohl Firmen geben, die das bereits Erfolgreich eingesetzt haben und die Enorme Zeit Ersparnisse nutzen.... auch das kann ich nicht beweisen/belegen....
Ein Projekt, welches in C X Tage dauert, dauert in Rust z.b. nur locker die Hälfte der Tage.... auch wenn man zum teil vier mal alles schreiben muss... Bei Rust, muss man, schreiben, was man nicht möchte...

Das soll jetzt nicht heißen, dass ich gegen Pascal bin, ich verwende es, weil die Sprache so Einfach...ist... Dabei gilt Pascal als extrem Schwierig... auch das kann ich nicht beweisen oder belegen....

Aber wir sind ja hier bei C bzw. C++....
MFG
Michael Springwald
Aktuelles Projekt: PlutoArduino
pluto
 
Beiträge: 6827
Registriert: 19. Nov 2006, 12:06
Wohnort: Oldenburg/Oldenburg
OS, Lazarus, FPC: Linux Mint 18.3 | 
CPU-Target: AMD
Nach oben

Beitragvon Timm Thaler » 14. Jan 2019, 18:48 Re: C Eigenarten

pluto hat geschrieben:Nicht nur das.
Was ist mit dem beliebten Buffer Überlauf?


Könnt ihr das nicht im µC.net Forum weiter diskutieren? Ich hab noch keine Programm für die Abendgestaltung, und so ein schön blutiges Splattermovie käme mir recht. ;-)

Der Witz ist ja immer, wenn Du sowas bei C-Freaks ansprichst: Aber man kann ja die ganze Compilerwarnungen anschalten, und dann gibts damit keine Probleme. Und der nächste Bufferüberlauf zeigt dann, dass C-Programmierer einfach zu cool sind um die Compilerwarnungen anzuschalten.

Bild

Der FPC hätte hier wenigstens ein "unreachable code" gebracht. Der C-Compiler wahrscheinlich auch. Muss also jemand ignoriert oder abgeschaltet haben.
Timm Thaler
 
Beiträge: 779
Registriert: 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
Nach oben

Beitragvon Timm Thaler » 14. Jan 2019, 18:54 Re: C Eigenarten

pluto hat geschrieben:"Ich habe gehört" C hat einen sehr guten Optimierer.... Das ist einer der Gründe warum es so erfolgreich sein soll...


Ich hab zumindest für AVR embedded mal an einigen Stellen den Quellcode verglichen, da nimmt sich das aktuelle FPC nix zum AVR-GCC. Man sollte allerdings auch die Optimierung nicht auf 0 stehen lassen.

Was bei PC-Programmen mit GUI die Exes wirklich hochtreibt sind die Widgetsets. Da ist ein Terminal mit ein paar Buttons unter FPC mit GTK schonmal 2MB groß, unter C mit Qt5 sind es 6MB + die Qt-Lib - und mit Purebasic braucht das funktional gleiche Terminal 56kB. Ja, KILObyte. Einfach weil es die WinApi ziemlich optimal nutzt.
Timm Thaler
 
Beiträge: 779
Registriert: 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
Nach oben

Beitragvon Warf » 14. Jan 2019, 18:56 Re: C Eigenarten

pluto hat geschrieben:ja, vielleicht ist der Fehler, ich kann aber doch, da nicht hinspringen, wenn ich gar nicht weiß wo es steht?

Der Compiler läuft mehrfach über das Dokument drüber (zumindest bei C, beim FPC keine ahnung, denke aber auch), beim erstel lauf wird der dann alle labels identifizeren und beim zweiten lauf dann die gotos auflösen oder so.

Aber wenn der case "zu ende" ist, müsste doch Automatisch Schluss sein?

genau das will man eben by design nicht haben. Man wollte das Switch Case zu einer Jumping Table wird wie man sie aus assembler kennt, daher ist nach dem case auch kein schluss. Die entwickler von C haben C eher als eine art Lesbares Assembler statt als eine High level Language gesehen

Ja, C ist einfach... dann liegt es wohl daran, dass der Compiler einfach nicht drauf hinweist, bei den Standard Einstellungen.

Die standardeinstellungen sind eh schrott, g++ 8 standard wirft fast keine warnings und benutzt sogar nur c++14, das erste was ich bei nem neuen projekt mache sind die flags -std=c++17 -Wall -Wpedantic hinzuzufügen

Das sollte doch nicht gehen? Bar ist doch ein const?

Das hab ich mir auch gedacht, aber lokales const ist äquivalent zu dem keyword static aus C, es erzeugt also eine globale variable die nur lokal zugänglich ist.

Eigentlich solltem an auch hier Rust verwenden, für AVR gibt es noch keine Unterstützung, aber für STM32.... darum verwende ich auch Lieber C++...

C++ hat noch einige weitere Vorteile, so kann man praktisch jeden operator überladen (z.B. = oder deref operator was unter pascal nicht geht). Das kann einiges einfacher machen, bzw sehr sauberen Code erzeugen. Man kann von C++ halten was man will, aber die Stream operatoren << und >> sind gut durchdacht. Daher hab ich mir fürn AVR erstmal selbst eine SerialStream klasse für den uart geschrieben (ich verwende base avr-g++, hab den ganzen arduino kram also nicht und muss alles selbst machen)
Code: Alles auswählen
SerialStream ss;
char str[32];
ss >> str; // lesen
ss << "Hallo " << str << endl; // schreiben


Außerdem gibt es sehr viele Konzepte in C die ist in Pascal nicht so gibt... z.b. Templates oder so ähnlich... NameSpace oder so ähnlich....
Ob die Vorteile bringen weiß ich nicht...

Pascal ist von anfang an so designd worden das man keine Namespaces braucht, wenn es zwei man den selben bezeichner gibt kannst du einfach unitname.Bezeichner verwenden, man hat also impliziet bereits namespaces mit den Unitnamen. In C/C++ ist es komplett undefiniert was passiert wenn man zwei mal den gleichen bezeichner hat, und je nach kompiler kracht es, oder es wird geschluckt und irgendwas passiert.

Meine Vermutung ist aber, dass C so erfolgreich ist, weil es durch seine Universalität bei vergleichsweise niedriger Implementierungstiefe sehr viele Möglichkeiten bietet.

Der hauptgrund ist eher das damals Pascal noch richtig scheiße war. Ich hab mir das Urpascal mal angesehen, so gab es z.B. keine Bitoperationen und andere spielereien. Es war einzig und allein eine Lernsprache und wurde daher von "realprogrammierer" immer belächelt. Als Pascal besser wurde hatte C schon seine Position.

Du sagst ja, dass du aus Performancegründen auf C++ setzt. Der Performacevorteil ist aber nicht in der Sprache begründet, aus Pascal-Quellcode könnte das gleiche Binary erzeugt werden. Sondern die vorhandenen Compiler sind halt ausgefuchster. Was zum einen an der Marktposition liegt, aber zum anderen eben auch an der Sprache.


Jain, C++ bietet die Möglichkeiten Promises zu machen. Z.B. wenn du eine Funktion als Inline definierst versprichst du dem Compiler das jedes Vorkommen dieser Funktion byteweise Identisch ist. Außerdem gibt es in C++ das Keyword Const mit dem du nicht wie in Pascal speicherbereiche markierst, sondern Datentypen. Ein Const datentyp kann nicht einfach zu nicht Const gemacht werden. Du versprichst damit dem Compiler also, was auch immer passiert du kannst davon ausgehen das die daten sich nicht verändern. Und dann gibt es z.B. noch Referenzen, die sind praktisch wie Pointer nur mit dem Versprechen an den Compiler das sich der Pointer nach der Zuweisung nie ändert, und nie invalide wird.
Mit diesen informationen kann man einfach viel mehr optimieren (z.B. caching, etc.). In Pascal hat man einfach nicht die Möglichkeiten dem Compiler solche sachen mitzuteilen. Das braucht man aber meist auch nicht. Pascal wird nicht im High Performance Computing verwendet, und um erhlich zu sein, warum auch. Pascal ist am besten für Desktop entwicklung, da brauch ich nichts zu optimieren bis zum gehtnichtmehr. Und wenn doch lad ich einfach Ne C++ oder Fortran Bibliothek oder verwende inline assembler



Zum Thema C++ ist seltsam ist mir noch eingefallen, Konstruktoren In C++ sind super seltsam. Diese erzeugen das Objekt, anders als in anderen Sprachen wo sie nach der erzeugung des Objekts aufgerufen werden. Das bedeutet, im Konstruktor exsistiert noch nicht die vtable, man kann also keine virtuellen/überladenen Funktionen aufrufen. Da versteh ich komplett nicht warum das so ist, vor allem wenn man dann ne stunde oder so sich fragen muss warum der Compiler bei dem aufruf einer Funktion meckert
Warf
 
Beiträge: 1047
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon pluto » 14. Jan 2019, 19:04 Re: C Eigenarten

Könnt ihr das nicht im µC.net Forum weiter diskutieren? Ich hab noch keine Programm für die Abendgestaltung, und so ein schön blutiges Splattermovie käme mir recht.

Hast du den schon Popcorn und Cola?
Hier ist doch kein Großes Kino.... :)


Die standardeinstellungen sind eh schrott, g++ 8 standard wirft fast keine warnings und benutzt sogar nur c++14, das erste was ich bei nem neuen projekt mache sind die flags -std=c++17 -Wall -Wpedantic hinzuzufügen

Beim Linux Kernel soll das auch so sein, dass alle Warnungen Abgeschaltet wurden sind... nach dem Motto: wir machen schon keine Fehler...

Das hab ich mir auch gedacht, aber lokales const ist äquivalent zu dem keyword static aus C, es erzeugt also eine globale variable die nur lokal zugänglich ist.

Unfassbar, dann kann ich ja gleich eine Normale Variable nehmen.

Daher hab ich mir fürn AVR erstmal selbst eine SerialStream klasse für den uart geschrieben (ich verwende base avr-g++, hab den ganzen arduino kram also nicht und muss alles selbst machen)

Da würde ich auch noch ganz hin, aber ich habe noch mit einigen Sachen so meine Probleme, z.b. mit der Register Installisierung bei...

Pascal ist von anfang an so designd worden das man keine Namespaces braucht, wenn es zwei man den selben bezeichner gibt kannst du einfach unitname.Bezeichner verwenden, man hat also impliziet bereits namespaces mit den Unitnamen

Stimmt natürlich... ist halt nur blöd, wenn man lange ein Fehler sucht.... und der FPC nimmt die Funktion aus der ersten unit und irgendwann kommst du drauf, ah es gibt noch mehr....

Der hauptgrund ist eher das damals Pascal noch richtig scheiße war. Ich hab mir das Urpascal mal angesehen, so gab es z.B. keine Bitoperationen und andere spielereien. Es war einzig und allein eine Lernsprache und wurde daher von "realprogrammierer" immer belächelt. Als Pascal besser wurde hatte C++ schon seine Position.

Oh, so schlimm war das Urpascal, dass Erklärt einiges...
MFG
Michael Springwald
Aktuelles Projekt: PlutoArduino
pluto
 
Beiträge: 6827
Registriert: 19. Nov 2006, 12:06
Wohnort: Oldenburg/Oldenburg
OS, Lazarus, FPC: Linux Mint 18.3 | 
CPU-Target: AMD
Nach oben

Beitragvon Timm Thaler » 14. Jan 2019, 19:24 Re: C Eigenarten

pluto hat geschrieben:Unfassbar, dann kann ich ja gleich eine Normale Variable nehmen.


Nee, die wäre dann ja wieder global zugreifbar.

Der Umweg bei Pascal über Const - wobei man ja schonmal den gedanklichen Spagat machen muss, dass eine Konstante nicht konstant ist - mißfällt mir auch, ich hätte das lieber sowas wie static.

Nur für AVR embedded ist es wirklich besser, wenn man eine Variable die erhalten bleiben soll global definiert anstatt per const als static, weil dann die Zugriffe wirklich schneller gehen.
Timm Thaler
 
Beiträge: 779
Registriert: 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
Nach oben

Beitragvon Warf » 14. Jan 2019, 19:40 Re: C Eigenarten

pluto hat geschrieben:Da würde ich auch noch ganz hin, aber ich habe noch mit einigen Sachen so meine Probleme, z.b. mit der Register Installisierung bei...


Ist halt immer 2 Stunden Datenblatt lesen, ne halbe Stunde beispiele Suchen und dann irgendwann hat man den AHA moment. Ich hab mich bewusst dafür entschieden erst gar nicht mit der Arduino IDE anzufangen, denn ich wollte von Anfang an lernen wie es richtig geht. Ich schau aber sehr oft in den Arduino Source Code und versuche das dann entsprechend (weniger generisch) nachzubauen. Wenn man z.B. einfach einen Pin oszilieren lassen will (also an und auschalten) bekommt man durch das hardware arbeiten das ganze ungefähr 2-4x so schnell hin wie mit der Arduino sprache, einfach weil da so viel an arbeit dran hängt (vor allem die Konvertierung der Pin Nummern zu den Registern und Bits ist recht aufwendig), und es macht mir auch einfach mehr spaß direkt auf dem Metall zu arbeiten (Außerdem erlaubt mir die Atmel Studio/MPLAB X IDE das einfache In Circuit Debugging, auch wenn ich mir dafür für nicht wenig geld erstmal die entsprechende Hardware kaufen musste)
Warf
 
Beiträge: 1047
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Timm Thaler » 14. Jan 2019, 21:35 Re: C Eigenarten

Warf hat geschrieben:Ist halt immer 2 Stunden Datenblatt lesen, ne halbe Stunde beispiele Suchen und dann irgendwann hat man den AHA moment...


Das ist aber nur am Anfang so. Später fragst Du Dich, wie die Leute mit dieser Krücke Arduino überhaupt arbeiten können, wenn man doch die Controller viel effizienter nutzen kann.

Zumal die Arduino-Leute die 2 Stunden Datenblatt lesen dann hinten wieder dreifach dranhängen, wenn sie anfangen den Grund zu suchen, warum ihre Soft-PWM nicht mehr funktioniert, wenn sie den Timer einschalten.
Timm Thaler
 
Beiträge: 779
Registriert: 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
Nach oben

Beitragvon pluto » 14. Jan 2019, 21:43 Re: C Eigenarten

Zumal die Arduino-Leute die 2 Stunden Datenblatt lesen dann hinten wieder dreifach dranhängen, wenn sie anfangen den Grund zu suchen, warum ihre Soft-PWM nicht mehr funktioniert, wenn sie den Timer einschalten.

Ich denke, lesen alleine wird natürlich nicht ausreichen... Du musst es auch verstehen können und auch wissen, wie man es dann umsetzt, egal in welcher Programmiersprache...

Ich habe gesehen, wie man ohne Arduino "zeug" einen atTiny84 "steuern" kann... da ging es um 2 RGB led's plus 4 Potis...
Die RGB LED'S werden hier über soft-pwm angesteuert, wir Arbeiten hier auf Register ebene, zum größten teil verstehe ich den Code, ob ich ihn selbst Anwenden könnte, weiß ich nicht...
Ist aber schon Interessant aufgebaut... Der Vorteil ist halt: Das wir alle 6 LED'S direkt und aufeinmal setzten können während es bei digitalWrite z.b. nicht der Fall ist... Jedenfalls nicht in der Form, die von Arduino angeboten wird.
MFG
Michael Springwald
Aktuelles Projekt: PlutoArduino
pluto
 
Beiträge: 6827
Registriert: 19. Nov 2006, 12:06
Wohnort: Oldenburg/Oldenburg
OS, Lazarus, FPC: Linux Mint 18.3 | 
CPU-Target: AMD
Nach oben

• Themenende •

Zurück zu Programmierung



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

porpoises-institution
accuracy-worried