Forum: Compiler & IDEs WinAVR: Keine Deklaration direkt nach case xyz:?


von Philipp B. (philipp_burch)


Lesenswert?

Hallo zusammen,

ich bekomme beim Code
1
  switch (OCR1A) {
2
    case 1:
3
      uint8_t blub = 7;
4
      usart_send_var("blub", blub);
5
      break;
6
  }
 jeweils den Fehler "../src/main.c:48: error: expected expression before 
'uint8_t'". Wenn ich aber direkt nach dem : eine Funktion aufrufe, oder 
auch nur ein einzelnes Semikolon schreibe, dann kompiliert das Prog ohne 
Fehler/Warnungen. Das Problem lässt sich auch durch das Einpacken des 
case-Blocks (case 1: {...}) beheben. Google hat mir dazu z.B. sowas 
gegeben: http://www.thescripts.com/forum/thread663830.html
Anscheinend ist das hier aber etwas anderes, da ich den Fehler durch das 
Semikolon umgehen kann. Ausserdem ändert es nichts, wenn ich die 
Definition von der Deklaration trenne.

Kann mir jemand sagen, was hier das Problem ist? Vielleicht ein Bug im 
GCC?
Es hat übrigens auch nix mit dem IO-Register als Switch-Variable zu tun.

Danke und Gruss,
Philipp

von Simon K. (simon) Benutzerseite


Lesenswert?

Hängt das nicht damit zusammen, dass Variablen immer nur am Anfang eines 
Blockes definiert werden dürfen? (Zumindest nach einem der (alten?) 
C-Standards)

Wobei das auch keinen Sinn macht - er erwartet ja etwas VOR der 
Variablendeklaration.

von Philipp B. (philipp_burch)


Lesenswert?

Ich nehme an, es ist schon etwas in der Richtung, doch das erklärt 
nicht, warum es denn mit einer (leeren) Anweisung davor funktioniert.

@Rufus t. Firefly:

Hast du vorhin etwas gepostet? Ich habe 'ne Mail bekommen, dass du auf 
den Beitrag geantwortet hast, doch da ist nix...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Habe mir eben die C99-Syntax nochmal angeguckt.  Nach einem Label
(also auch nach einem case-Label) muss ein statement stehen.
Eine Deklaration ist kein statement.  Innerhalb eines Blocks
(also innerhalb geschweifter Klammern) dürfen ansonsten statements
und declarations beliebig gemischt werden (das nennt sich dann ein
"block-item" in der Syntaxbeschreibung).

Du musst es also als eigenen Block schreiben:
1
  switch (OCR1A) {
2
    case 1:
3
    {
4
      uint8_t blub = 7;
5
      usart_send_var("blub", blub);
6
      break;
7
     }
8
  }

Aus dem gleichen Grund darf am Ende kein einzelner Label stehen,
also z. B.
1
  switch (OCR1A) {
2
    case 1: ... break;
3
    case 2: ... break;
4
    default:
5
  }

ist unzulässig, wird aber meiner Erinnerung nach vom GCC als language
extension toleriert.

von Philipp B. (philipp_burch)


Lesenswert?

Achso, besten Dank.
Aber kannst du mir auch sagen, warum das so ist? Irgendwie sehe ich den 
Sinn davon nicht so recht (Ich bin ja auch kein Compilerbauer).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Aber kannst du mir auch sagen, warum das so ist?

Da musst du die Leute fragen, die den C99-Standard geschrieben haben.

von Philipp B. (philipp_burch)


Lesenswert?

Ok, ich dachte, du als C-Guru wüsstest das vielleicht...

von Karl H. (kbuchegg)


Lesenswert?

Weil in C ein case nun mal keinen Block definiert.
Man kann ja auch durch einen case 'durchfallen'

1
switch c {
2
  case 0:
3
    int a;
4
    i = 5;
5
             // Achtung: kein break. D.h. Fallthrough
6
             // zum case 1
7
  case 1:
8
    int a;
9
    j = 8;
10
    break;
11
12
  case 2:
13
    ...
14
}

Wenn c den Wert 0 hat, dann fällt die Bearbeitung bis zum
case 1 durch. Nur: Dort gäbe es jetzt plötzlich 2 Variablen
namens 'a'.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:

> Weil in C ein case nun mal keinen Block definiert.

Nö, das zählt nicht. ;-)  In C99 darf man ja statements und
declarations mischen, da musst du auch auf die Eindeutigkeit
der Namen innerhalb ihres jeweiligen Scopes achten.

von Philipp B. (philipp_burch)


Lesenswert?

Ja, das finde ich ja auch logisch, aber warum ist es denn plötzlich 
gültig, wenn da noch eine andere Anweisung davor ist?
1
switch (c) {
2
  case 1:
3
  case 2:
4
    init_ports();
5
    int x = 5;   //ok
6
    break;
7
  case 3:
8
    ;
9
    int y = 7;   //ok
10
    break;
11
  case 4:
12
    int z = 3;   //"error: expected expression before 'int'"
13
    break;
14
}
hö?

Wenn ich bei case 3 ebenfalls x verwende, gibt's dort auch einen Fehler 
(redefinition).

EDIT: Da war Jörg wohl schneller...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Aber genau das ist es doch:
1
int b;
2
switch c {
3
  case 0:
4
    int a;
5
    a = 5;
6
    break;
7
8
  case 1:
9
    b = a;
10
    break;
11
12
  case 2:
13
    ...
14
}

Da int a in allen auf die Deklaration/Definition folgenden Zeilen des 
aktuellen Blocks bekannt ist, ist int a also auch nach dem Label "case 
1" bekannt und die Zuweisung zulässig. Auch ohne "Fall-Through".

Da aber dieses Label angesprungen werden kann, ohne daß der auf das 
Label "case 0" folgende Code ausgeführt wird, der sich um die 
Deklaration/Definition und Initialisierung von int a kümmert, ist int a 
zum Zeitpunkt des Anspringen von "case 1" bels nicht bekannt und 
zumindestens nicht initialisiert.

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch wrote:
> Karl heinz Buchegger wrote:
>
>> Weil in C ein case nun mal keinen Block definiert.
>
> Nö, das zählt nicht. ;-)  In C99 darf man ja statements und
> declarations mischen, da musst du auch auf die Eindeutigkeit
> der Namen innerhalb ihres jeweiligen Scopes achten.

Auch wieder wahr.
Im Moment ist die Scope Regel ja ziemlich simpel:
Wird ein } erreicht, dann endet ein Scope.
Nimmst du jetzt noch Spezialregeln für case dazu, dann
führst du zusätzliche Scope Regeln ein, die normalerweise
niemand wirklich braucht.
Der scope endet, wenn
  * ein } erreicht wird
  * ein anderer case erreicht wird
  * ein default erreicht wird

Eine ursprünglioch einfache Regel wird dadurch unnötig
kompliziert, ohne dass es dem Programmierer irgendetwas
bringt (das bischen Schreibaufwand für die { } zähle
ich mal nicht). Ich denke mal, davor ist man zurückgeschreckt.
Ach wäre man blos beim return in non-void Funktionen auch
so konsequent gewesen :-)
Der switch-case ist in C sowieso schon ein abartiger Bastard,
der seltsame Eigenschaften hat. Ich sag nur: Duffs Device.

von Karl H. (kbuchegg)


Lesenswert?

Philipp Burch wrote:
> Ja, das finde ich ja auch logisch, aber warum ist es denn plötzlich
> gültig, wenn da noch eine andere Anweisung davor ist?

Hmm. Interessant.
Das kann ich nicht erklären und ich denke auch nicht, dass
das so im C-Standard beabsichtigt ist.
Ich denke mal das ist ein Bug.

von Philipp B. (philipp_burch)


Lesenswert?

@Rufus:
1
int c;
2
int b;
3
switch (c) {
4
  case 0:
5
    ;
6
    int a;
7
    a = 5;
8
    break;
9
10
  case 1:
11
    b = a;
12
    break;
13
14
  case 2:
15
    break;
16
}

Mich verwundert, dass es so funktioniert, nicht, dass es ohne ';' nicht 
funktioniert.

@Alle:

Interessant ist, was er aus meinem kleinen Testprogramm macht (Ohne 
Optimierungen):
1
volatile int a = 3;
2
volatile int b = 7;
3
4
int main() {
5
  switch (a) {
6
    case 1:
7
      ;
8
      int x = 7;
9
      b = x;
10
      break;
11
    case 2:
12
      ;
13
      int y = 3;
14
      y = x;
15
    case 3:
16
      b = y;
17
      break;
18
    default:
19
      b = 0;
20
  }
21
22
  for (;;);
23
}
1
4:        int main() {
2
+0000002F:   93CF        PUSH    R28              Push register on stack
3
+00000030:   93DF        PUSH    R29              Push register on stack
4
+00000031:   B7CD        IN      R28,0x3D         In from I/O location
5
+00000032:   B7DE        IN      R29,0x3E         In from I/O location
6
+00000033:   9726        SBIW    R28,0x06         Subtract immediate from word
7
+00000034:   B60F        IN      R0,0x3F          In from I/O location
8
+00000035:   94F8        CLI                      Global Interrupt Disable
9
+00000036:   BFDE        OUT     0x3E,R29         Out to I/O location
10
+00000037:   BE0F        OUT     0x3F,R0          Out to I/O location
11
+00000038:   BFCD        OUT     0x3D,R28         Out to I/O location
12
5:          switch (a) {
13
+00000039:   91800060    LDS     R24,0x0060       Load direct from data space
14
+0000003B:   91900061    LDS     R25,0x0061       Load direct from data space
15
+0000003D:   839E        STD     Y+6,R25          Store indirect with displacement
16
+0000003E:   838D        STD     Y+5,R24          Store indirect with displacement
17
+0000003F:   818D        LDD     R24,Y+5          Load indirect with displacement
18
+00000040:   819E        LDD     R25,Y+6          Load indirect with displacement
19
+00000041:   3082        CPI     R24,0x02         Compare with immediate
20
+00000042:   0591        CPC     R25,R1           Compare with carry
21
+00000043:   F0B1        BREQ    PC+0x17          Branch if equal
22
+00000044:   818D        LDD     R24,Y+5          Load indirect with displacement
23
+00000045:   819E        LDD     R25,Y+6          Load indirect with displacement
24
+00000046:   3083        CPI     R24,0x03         Compare with immediate
25
+00000047:   0591        CPC     R25,R1           Compare with carry
26
+00000048:   F0C9        BREQ    PC+0x1A          Branch if equal
27
+00000049:   818D        LDD     R24,Y+5          Load indirect with displacement
28
+0000004A:   819E        LDD     R25,Y+6          Load indirect with displacement
29
+0000004B:   3081        CPI     R24,0x01         Compare with immediate
30
+0000004C:   0591        CPC     R25,R1           Compare with carry
31
+0000004D:   F009        BREQ    PC+0x02          Branch if equal
32
+0000004E:   C01A        RJMP    PC+0x001B        Relative jump
33
8:              int x = 7;
34
+0000004F:   E087        LDI     R24,0x07         Load immediate
35
+00000050:   E090        LDI     R25,0x00         Load immediate
36
+00000051:   839C        STD     Y+4,R25          Store indirect with displacement
37
+00000052:   838B        STD     Y+3,R24          Store indirect with displacement
38
9:              b = x;
39
+00000053:   818B        LDD     R24,Y+3          Load indirect with displacement
40
+00000054:   819C        LDD     R25,Y+4          Load indirect with displacement
41
+00000055:   93900063    STS     0x0063,R25       Store direct to data space
42
+00000057:   93800062    STS     0x0062,R24       Store direct to data space
43
10:             break;
44
+00000059:   C013        RJMP    PC+0x0014        Relative jump
45
13:             int y = 3;
46
+0000005A:   E083        LDI     R24,0x03         Load immediate
47
+0000005B:   E090        LDI     R25,0x00         Load immediate
48
+0000005C:   839A        STD     Y+2,R25          Store indirect with displacement
49
+0000005D:   8389        STD     Y+1,R24          Store indirect with displacement
50
14:             y = x;
51
+0000005E:   818B        LDD     R24,Y+3          Load indirect with displacement
52
+0000005F:   819C        LDD     R25,Y+4          Load indirect with displacement
53
+00000060:   839A        STD     Y+2,R25          Store indirect with displacement
54
+00000061:   8389        STD     Y+1,R24          Store indirect with displacement
55
16:             b = y;
56
+00000062:   8189        LDD     R24,Y+1          Load indirect with displacement
57
+00000063:   819A        LDD     R25,Y+2          Load indirect with displacement
58
+00000064:   93900063    STS     0x0063,R25       Store direct to data space
59
+00000066:   93800062    STS     0x0062,R24       Store direct to data space
60
17:             break;
61
+00000068:   C004        RJMP    PC+0x0005        Relative jump
62
19:             b = 0;
63
+00000069:   92100063    STS     0x0063,R1        Store direct to data space
64
+0000006B:   92100062    STS     0x0062,R1        Store direct to data space
65
22:         for (;;);
66
+0000006D:   CFFF        RJMP    PC-0x0000        Relative jump
67
+0000006E:   CFFF        RJMP    PC-0x0000        Relative jump

Beim kompilieren gibt's übrigens keine Warnungen...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:

> Das kann ich nicht erklären und ich denke auch nicht, dass
> das so im C-Standard beabsichtigt ist.

Doch, das sieht sehr gewollt aus im C-Standard.  Die freie Austausch-
barkeit von statements mit declarations ist nur in der Form eines
block-item (6.8.2 Compound statement) vorgesehen.  Ein labeled
statement (6.8.1) besteht aber aus einem label, gefolgt von einem
statement -- nicht einem block-item, wie es nötig wäre, um dort
noch eine declaration unterzubringen.

Eine Variablendeklaration darf man natürlich direkt vor dem Label
unterbringen:
1
  switch (OCR1A) {
2
    default:
3
      break;
4
5
      uint8_t blub;
6
    case 1:
7
      blub = 7;
8
      usart_send_var("blub", blub);
9
      break;
10
  }

Ansonsten eben einen eigenen Block aufmachen nach dem case label.


Philipp Burch wrote:

> Interessant ist, was er aus meinem kleinen Testprogramm macht (Ohne
> Optimierungen):

,,Interessant ist, wie langsam dieser Ferrari mit angezogener
Handbremse kriecht.''

Wer keine Optimierungen einschaltet, braucht sich auch nicht über
großen, umständlichen und langsamen Code beklagen.

von Philipp B. (philipp_burch)


Lesenswert?

> Philipp Burch wrote:
>
>> Interessant ist, was er aus meinem kleinen Testprogramm macht (Ohne
>> Optimierungen):
>
> ,,Interessant ist, wie langsam dieser Ferrari mit angezogener
> Handbremse kriecht.''
>
> Wer keine Optimierungen einschaltet, braucht sich auch nicht über
> großen, umständlichen und langsamen Code beklagen.

Ich wollte auch nicht auf die Umständlichkeit hinaus, sondern auf die 
Verwendung der Variablen, die eigentlich gar nicht existiert. Wenn ich 
das richtig sehe, wird die Variable erstellt (Aber nur bei der 
eigentlichen Deklaration und Definition initialisiert - ist ja auch 
logisch) und ist im gesamten switch-Block verfügbar. Jedenfalls ist man 
(Bzw. der Compiler) damit bestimmt auf der sicheren Seite.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Philipp Burch wrote:

> Ich wollte auch nicht auf die Umständlichkeit hinaus, sondern auf die
> Verwendung der Variablen, die eigentlich gar nicht existiert. Wenn ich
> das richtig sehe, wird die Variable erstellt (Aber nur bei der
> eigentlichen Deklaration und Definition initialisiert - ist ja auch
> logisch) und ist im gesamten switch-Block verfügbar. Jedenfalls ist man
> (Bzw. der Compiler) damit bestimmt auf der sicheren Seite.

Dann solltest du das dazu schreiben. ;-)

Der GCC legt den Stackframe immer für die gesamte Funktion an,
zwischendurch wird da (außer bei alloca(), da bin ich mir nicht so
sicher) nicht manipuliert.  Allerdings wird der Optimierer in aller
Regel das Zeug dann rauswerfen, und dann existieren die Werte der
jeweiligen Variablen wirklich oft nur für kurze Zeit in einem Register.

Weiter oben schriebst du:

> Mich verwundert, dass es so funktioniert, nicht, dass es ohne ';' nicht
> funktioniert.

Ganz einfach: dein Semikolon hat syntaktisch eine leere Anweisung
erzeugt, damit war das "labeled statement" abgeschlossen, und du
befindest dich wieder auf der Ebene, bei der sich statements und
declarations beliebig abwechseln dürfen.

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch wrote:
> Karl heinz Buchegger wrote:
>
>> Das kann ich nicht erklären und ich denke auch nicht, dass
>> das so im C-Standard beabsichtigt ist.
>
> Doch, das sieht sehr gewollt aus im C-Standard.  Die freie Austausch-
> barkeit von statements mit declarations ist nur in der Form eines
> block-item (6.8.2 Compound statement) vorgesehen.  Ein labeled
> statement (6.8.1) besteht aber aus einem label, gefolgt von einem
> statement -- nicht einem block-item, wie es nötig wäre, um dort
> noch eine declaration unterzubringen.
>
> Eine Variablendeklaration darf man natürlich direkt vor dem Label
> unterbringen:

Hmm. Ich sehe worauf du hinaus willst.
Allerdings muss ich mich jetzt deiner weiter oben aufgeworfenen
Frage anschliessen:
Was ist der tiefere Sinn dahinter?

Irgendwie macht das schon den Eindruck, als ob die Erlaubnis
für Deklarationen mitten in den Statements nicht so ganz 100%
durchgezogen wurde.

Auf der anderen Seite: Dieses Statement-Deklaration mischen
gibt es ja in C++ schon länger als in C. In den entsprechenden
Normierungsgremien sind fähige Köpfe, sodass ich zuallererst
mal von der Annahme ausgehe, dass es da irgendeinen pathologischen
Fall gibt, der Probleme macht. Nur: ich finde ihn nicht. (Und
das macht mich wahnsinnig:-)

von Andreas K. (a-k)


Lesenswert?

Da wäre noch der subtile Unterschied zwischen dem was man syntaktisch 
darf, und dem was inhaltlich zulässig ist. Nicht alles was syntaktisch 
geht ist auch erlaubt.

Dass man syntaktisch hinter Deklarationen springen darf, liegt an der 
sonst erheblich komplexeren Syntax.

Dass man das dennoch nicht darf ist dann einen inhaltliche 
Angelegenheit. Ein Compiler darf durchaus auch erst an der Stelle der 
Variablendefinition den Stack-Frame aufbauen, wenn er das für sinnvoll 
hält. Wird er üblicherweise nicht tun, jedenfalls nicht wenns nur um dem 
Platz geht, weshalb es dann trotzdem funktioniert, aber es bleibt 
offiziell illegal, hinter eine Definition zu springen.

Als Illustration mag ein Destruktor in C++ dienen. Der muss beim 
Verlassen des Gültigkeitsbereichs aufgerufen werden. Was schon innerhalb 
der Funktion geschehen kann, nicht erst am Ende. Und Analoges gilt dann 
natürlich auch für den dazu passenden Konstruktor.

Der tiefere Sinn hinter der syntaktischen Eigenheit von Labels kann auch 
schlicht in etwas liegen, was man bei anderer Gelegenheit als deutsches 
Credo bezeichnen könnte: "das war schon immer so, da könnte ja jeder 
kommen, wo kämen wir da hin" ;-). Schon die erste formale Syntax von 
C/C++ war nicht der grosse Wurf und sie entwickelte sich aufgrund von 
Anfangsfehlern mit der Zeit und den Standards von naja (K&R Original) 
bis kotzwürg (C++).

von Gast (Gast)


Lesenswert?

> Schon die erste formale Syntax von
>C/C++ war nicht der grosse Wurf und sie entwickelte sich aufgrund von
>Anfangsfehlern mit der Zeit und den Standards von naja (K&R Original)
>bis kotzwürg (C++).

Wow - kannst du da mal ein paar beispiele liefern. Ich stecke da nicht 
so drin, und dachte bisher, dass C bzw. C++ gut und effizient seien.

Danke.

von Andreas K. (a-k)


Lesenswert?

> Wow - kannst du da mal ein paar beispiele liefern. Ich stecke da nicht
> so drin, und dachte bisher, dass C bzw. C++ gut und effizient seien.

Ich bezog mich ausdrücklich auf die formale Syntax, nicht auf Dinge wie 
Nützlichkeit, Effektivität, Effizienz (anderes Thema).

Die allererste Version von C hatte keine typedefs. Bis dahin war die 
Welt syntaktisch leidlich in Ordnung (ja, das else-Problem war schon 
da). Dann kamen typedefs und aus normalen Namen wurden halbe 
Schlüsselwörter. Der Compiler musste fortan typdef-Namen und die übrigen 
Namen bereits im Parser auseinanderhalten. Weil man nur so eine 
Deklaration erkennt. Wirth wusste es mitsamt der übrigen Algol-Gemeinde 
besser und hat in Pascal CONST/VAR vorangestellt.

Dann kam Stroustrup und mutierte Datentypen zu Operatoren. Damit war 
typename(x) nun Typkonvertierung oder Konstruktoraufruf. Vorher war es 
die Deklaration von x mit überflüssiger Klammer drumrum. Syntaktisch 
funktioniert beides, entscheidbar nur durch Konvention.

Weiter meinte Stroustrup, dass man die Initializer der Basisklassen per 
Doppelpunkt einleitet. Also
  classname(parameter) : (initializer) { ... }
Mal abgesehen davon, dass der classname hier syntaktisch genauso blöd 
dasteht wie die oben erwähnten typedefs, erinnert das syntaktisch bis 
zur geschweiften Klammer stark an ein Bitfeld.

von Andreas K. (a-k)


Lesenswert?

> Wow - kannst du da mal ein paar beispiele liefern. Ich stecke da nicht
> so drin, und dachte bisher, dass C bzw. C++ gut und effizient seien.

Zum anderen Thema: Der Erfolg von C und C++ hat wenig mit Qualität zu 
tun. C war zum richtigen Zeitpunkt am richtigen Platz. In den 70ern gabe 
es an Compilersprachen hauptsächlich FORTRAN 66, COBOL, Algol, Pascal, C 
und PL/1.

Davon ist PL/1 erstens eine nackte Katastrophe, zweitens so stark mit 
IBM verklebt dass es niemand sonst in die Finger nehmen wollte.

COBOL ist für wirklich alles ungeeignet, besonders ungeeignet aber für 
alles ausserhalb der kaufmännischen Sphäre. Und FORTRAN 66 fehlt vieles 
was Informatiker so lieben, beispielsweise die Rekursion.

Pascal ist sprachlich sauber konstruiert, aber wie alle Sprachen von 
Wirth für genau einen einzigen Einsatzzweck. In diesem Fall den 
Anfangssemestern das Programmieren beizubringen. Mehr geht damit nicht. 
Jedenfalls nicht mit dem Sprachumfang den Wirth definierte.

Blieb praktisch nur C übrig (von Algol weiss ich zu wenig). Das war 
einfach da und konnte irgendwie fast alles was man benötigte. Und nicht 
nur als Sprache, sondern gleich auch noch mitsamt Betriebssystem, 
Compiler und vergleichsweise günstiger Maschine (PDP11) dazu. Inklusive 
kostenlosem Quellcode, sowohl vom Compiler als auch vom Betriebssystem. 
Wie geschaffen um an Unis damit herumzuspielen.

Was also konnte und wollte man an Unis verwenden?

Was also haben dann all jene verwendet, die von Assembler weg wollten 
und eine Sprache brauchten, mit denen man nicht nur Gehälter oder 
Umlaufbahnen berechnen kann, sondern Betriebssysteme, Compiler, 
interaktive Programme, ... programmieren?

Und so ist C zwar ungemein populär, aber wer mit mit Programmiersprachen 
nicht nur programmiert, sondern sich auch ein bischen mit deren 
Systematik und Potential (positiv wie negativ) auseinandersetzt, der ist 
vom Siegeszug von C alles andere als begeistert.

Und da C++ die negativen Eigenschaften von C der Kompatibilität zuliebe 
sämtlich geerbt hat, kann man dem, was sprachlich hätte geordnet werden 
können, eben nur durch Disziplin und Konvention beikommen. So man davon 
hat.

Um das mal auf das Thema dieses Boards zu bringen: Für Controller der 
AVR-Klasse braucht man eine Sprache, die ziemlich genau den 
Anforderungen der 70er entspricht. Dafür ist C bei aller Kritik 
einigermassen brauchbar, die Hardware-Nähe hat man da ja sowieso. Ada 
wäre mir zwar erheblich lieber, aber mehr als ein paar kleine 
Spielplätze für Aussenseiter wird da nicht mehr herauskommen.

von Andreas K. (a-k)


Lesenswert?

PS: Das ist wie mit x86-Prozessoren. Absolut jeder, der sich mit dem 
Thema Rechnerarchitektur ein bischen auskennt, schimpft darüber. Aber 
sie sind halt da und man muss damit leben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.