Forum: Mikrocontroller und Digitale Elektronik Modulo in C richtig


von Cman (Gast)


Lesenswert?

Wieso ist nochmal so etwas in C nicht gut?

counter = counter++ % 10;
Danke

von Jim M. (turboj)


Lesenswert?

Wegen dem Post Inkrement.

Das hier wäre besser, solange counter nicht volatile ist:
1
counter = ++counter % 10;

Beitrag #5622230 wurde vom Autor gelöscht.
von Kaj (Gast)


Lesenswert?

Cman schrieb:
> Wieso ist nochmal so etwas in C nicht gut?
Undefined Behavior
1
int main(void)
2
{
3
    int counter = 337;
4
    counter = counter++ % 10;
5
6
    return 0;
7
}
1
$ gcc -std=c99 -Wall -Wextra -o main main.c 
2
main.c: In function 'main':
3
main.c:8:13: warning: operation on 'counter' may be undefined [-Wsequence-point]
4
     counter = counter++ % 10;
5
     ~~~~~~~~^~~~~~~~~~~~~~~~

Jim M. schrieb:
> Das hier wäre besser
Nein, ist genauso schlecht.
1
int main(void)
2
{
3
    int counter = 337;
4
    counter = ++counter % 10;
5
6
    return 0;
7
}
1
$ gcc -std=c99 -Wall -Wextra -o main main.c 
2
main.c: In function 'main':
3
main.c:8:13: warning: operation on 'counter' may be undefined [-Wsequence-point]
4
     counter = ++counter % 10;
5
     ~~~~~~~~^~~~~~~~~~~~~~~~

von Cman (Gast)


Lesenswert?

und warum ist das undefined?

von M. K. (sylaina)


Lesenswert?

Cman schrieb:
> und warum ist das undefined?

Na fragen wir doch mal anders: Welchen Sinn hätte die Operation denn? 
Mir fiele auch nach längerem Nachdenken keine Anwendung ein, bei der man 
z.b. erst eine Variable um 1 erhöht, eine Modulo-Operation darauf 
anwendet und das Ergebnis dann in die selbe Variable zurückschreibt. Ich 
mein, ich fände das mal interessant wo so etwas sinnvoll sein soll. 
Klingt für mich zunächst mal für einen ungünstigen Algorithmus der 
Optimierungspotential beinhaltet.

von A. S. (Gast)


Lesenswert?

Cman schrieb:
> und warum ist das undefined?

Weil das = kein Sequence Point ist. D.h., es ist unklar, ob das ++ vor 
oder nach der Zuweisung kommen müsste. Und so unklar, dass dabei alles 
schief gehen kann und der Compiler 100 Zeilen vorher 7 Bytes im opcode 
drehen darf. Oder WW3 auslösen.

von Rolf M. (rmagnus)


Lesenswert?

Cman schrieb:
> und warum ist das undefined?

Man darf zwischen zwei Sequenzpunkten eine Variable nicht mehrmals 
beschreiben. Sie wird hier aber einmal durch das = und einmal durch das 
++ geschrieben. Der einzige Sequenzpunkt dieser Zeile ist bei dem 
Semikolon am Ende.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

1
counter = (counter + 1) % 10;

ist vermutlich zu einfach zu schreiben. :-))

von Kaj (Gast)


Lesenswert?

Diese ganze Sache hatten wir doch aber gerade schon mal...
Beitrag "Dekrementieren vs. Subtrahieren (n-- vs n-1)"

von Cman (Gast)


Lesenswert?

M. K. schrieb:
> Cman schrieb:
>> und warum ist das undefined?
>
> Na fragen wir doch mal anders: Welchen Sinn hätte die Operation denn?
> Mir fiele auch nach längerem Nachdenken keine Anwendung ein, bei der man
> z.b. erst eine Variable um 1 erhöht, eine Modulo-Operation darauf
> anwendet und das Ergebnis dann in die selbe Variable zurückschreibt. Ich
> mein, ich fände das mal interessant wo so etwas sinnvoll sein soll.
> Klingt für mich zunächst mal für einen ungünstigen Algorithmus der
> Optimierungspotential beinhaltet.

Wenn du einen Wert hast mit dem Typen uint8_t und du willst zB für eine 
Uhr nur von 0 bis 59 zählen?

Rolf M. schrieb:
> Cman schrieb:
>> und warum ist das undefined?
>
> Man darf zwischen zwei Sequenzpunkten eine Variable nicht mehrmals
> beschreiben. Sie wird hier aber einmal durch das = und einmal durch das
> ++ geschrieben. Der einzige Sequenzpunkt dieser Zeile ist bei dem
> Semikolon am Ende.

Danke ;)

Jörg W. schrieb:
> counter = (counter + 1) % 10;
> ist vermutlich zu einfach zu schreiben. :-))

Danke ;)

Kaj schrieb:
> Diese ganze Sache hatten wir doch aber gerade schon mal...
> Beitrag "Dekrementieren vs. Subtrahieren (n-- vs n-1)"

Danke ;)

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


Lesenswert?

Cman schrieb:
> Wenn du einen Wert hast mit dem Typen uint8_t und du willst zB für eine
> Uhr nur von 0 bis 59 zählen?

Das ist doch trotzdem kein Grund, auf die gleiche Variable innerhalb der 
Operation zweimal einen Wert zuweisen zu wollen (und noch dazu nicht 
den gleichen).

Du vergisst, dass die Eingangszeile eine Kurzform ist von
1
counter = (counter = counter + 1) % 10;

Siehst du jetzt die doppelte Zuweisung?

von A. S. (Gast)


Lesenswert?

Cman schrieb:
> willst zB für eine Uhr nur von 0 bis 59 zählen?

Ja, da geht der % Operator. lesbarer (schneller, robuster) ist
1
If(++counter > 59) {counter = 0;}
Da ist sofort klar, dass nicht wirklich Modulo sondern nur Überlauf 
gemeint ist.

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> If(++counter > 59) {counter = 0;}

Das funktioniert nur, wenn man immer, und für alle Zeiten, GARANTIEREN 
kann, dass counter nicht woanders verändert wird.

> counter = (counter + 1) % 60;
Ist im dem Punkt erheblich robuster

von Wilhelm M. (wimalopaan)


Lesenswert?

Geht es darum, einen integralen Datentyp zu haben, der einen 
Wertebereich
[0,59] besitzt?

Dann schreibt man sich ihn:
1
template<typename T, T Lower, T Upper>
2
requires std::is_integral<T>::value
3
class uint_ranged {
4
    //...
5
};
6
7
uint_ranged<uint8_t, 0, 59> x;

Leider kann das C nicht ...

von Dr. Sommer (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Ist im dem Punkt erheblich robuster

Und je nach Plattform erheblich langsamer.

Arduino Fanboy D. schrieb:
> GARANTIEREN kann, dass counter nicht woanders verändert wird.

Dazu kapselt man ihn in eine Klasse die keine anderen Schreibzugriffe 
zulässt.

von Rolf M. (rmagnus)


Lesenswert?

Arduino Fanboy D. schrieb:
> Achim S. schrieb:
>> If(++counter > 59) {counter = 0;}
>
> Das funktioniert nur, wenn man immer, und für alle Zeiten, GARANTIEREN
> kann, dass counter nicht woanders verändert wird.
>
>> counter = (counter + 1) % 60;
> Ist im dem Punkt erheblich robuster

Wenn man das unbedingt braucht kann man aber auch einfach schreiben:
1
if (++counter > 59) {counter -= 60;}
Dann passiert genau das selbe wie bei der Modulo-Operation, solange der 
Wert nicht zwischen zwei Aufrufen dieses Codes mehr als einmal 
überläuft. Sollte das der Fall sein, würde auch nocht gehen:
1
++counter;
2
while (counter > 59) {counter -= 60;}

Ich schreibe in so einem Fall die Inkrememntierung eh normalerweise in 
eine eigene Zeile.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Jörg W. schrieb:
> counter = (counter + 1) % 10;

Auf MCs ohne HW-Division muß dazu aber die Math-Lib aufgerufen werden, 
d.h. es kann dauern und das jedesmal. Effizienter ist daher ein 
Vergleich.
Da diese Aufgabe recht oft auftritt, habe ich mir dafür ein Macro 
geschrieben:
1
#define ROLLOVER( x, max )  x = ++x >= max ? 0 : x
Man beachte, x läuft von 0 bis max-1.
Der Ternary Operator ist ein Sequence Point, d.h. ++x wird zuerst 
ausgeführt.

von Dr. Sommer (Gast)


Lesenswert?

Profis™ machen das so:
1
#include <cstdint>
2
#include <iostream>
3
4
template <typename T, T Max>
5
class Counter {
6
  public:
7
    constexpr Counter (T v = 0) : value (v) {}
8
    operator T () const { return value; }
9
    T get () const { return value; }
10
    Counter& count () { if (++value == Max) value = 0; return *this; }
11
  private:
12
    T value;
13
};
14
15
int main () {
16
  Counter<uint8_t, 3> counter3;
17
  
18
  for (std::int8_t i = 0; i < 10; ++i)
19
    std::cout << int { counter3.count () } << std::endl;
20
}
Keine Division, keine Möglichkeit einen zu hohen Wert zuzuweisen.

von Wilhelm M. (wimalopaan)


Lesenswert?

Dr. Sommer schrieb:
> Profis™ machen das so:

Aber Du weißt doch, dass Du in diesem Forum eine C Frage nicht mit C++ 
beantworten darfst!!!

Zumindest hatte ich oben noch den Hinweis dazu geschrieben, dass C das 
nicht kann :-)

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Cman schrieb:
> Wenn du einen Wert hast mit dem Typen uint8_t und du willst zB für eine
> Uhr nur von 0 bis 59 zählen?

Hm, das hätte ich auch mit einer if-Bedingung gelöst aber ok, das wäre 
in der Tat eine Anwendungsmöglichkeit.

von Wilhelm M. (wimalopaan)


Lesenswert?

Dr. Sommer schrieb:
> Profis™ machen das so:

> Keine Division, keine Möglichkeit einen zu hohen Wert zuzuweisen.

Beim CTor wäre ich vorsichtig, eine Assertion wäre sinnvoll.

von Dr. Sommer (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Beim CTor wäre ich vorsichtig, eine Assertion wäre sinnvoll.

Guter Punkt, dann so:
1
constexpr Counter (T v = 0) : value (v) { assert (v < Max); }

Wilhelm M. schrieb:
> Aber Du weißt doch, dass Du in diesem Forum eine C Frage nicht mit C++
> beantworten darfst!!!
Sonst kommt die C-Polizei!

von Peter D. (peda)


Lesenswert?

Dr. Sommer schrieb:
> Sonst kommt die C-Polizei!

Das nicht, aber ein Großteil der Leser wird damit nichts anfangen 
können.
Du hättest Deinen Beitrag genauso gut in chinesisch posten können.

von Dr. Sommer (Gast)


Lesenswert?

Peter D. schrieb:
> Auf MCs ohne HW-Division muß dazu aber die Math-Lib aufgerufen werden,

Das ist sogar auf einigen der großen ARM Cortex-A so. Die haben 
ebenfalls keine Hardware-Division (da man Division so selten braucht, 
ist es sinnvoller die Chipfläche für mehr Cache, Branch-Prediction usw. 
zu nutzen). Da ARM aber generell sehr effizient kurze bedingte Blöcke 
ausführen kann (Conditional Execution) ist die Variante mit "if" auf dem 
Cortex-A erst recht deutlich schneller. Das wird dann zu:
1
add r0, #1
2
cmp r0, #10
3
movhs r0, #0
Ist der Modulo-Divisor allerdings einer 2er-Potenz (z.B. 8), wird der 
Compiler das "%" zu einem "And" optimieren, was dann noch schneller als 
das "if" sein sollte (auch auf ARM):
1
add r0, #1
2
and r0, #0x7

Peter D. schrieb:
> Das nicht, aber ein Großteil der Leser wird damit nichts anfangen
> können.
Vielleicht denkt man sich dann, dass es vielleicht doch keine schlechte 
Idee ist mal über den C-Horizont hinaus zu blicken.

von Wilhelm M. (wimalopaan)


Lesenswert?

Dr. Sommer schrieb:
> Wilhelm M. schrieb:
>> Beim CTor wäre ich vorsichtig, eine Assertion wäre sinnvoll.
>
> Guter Punkt, dann so:
>
1
constexpr Counter (T v = 0) : value (v) { assert (v < Max); }
>

Würde den Typwandlungs-Ctor auch abschalten ;-)

von Wilhelm M. (wimalopaan)


Lesenswert?

Peter D. schrieb:
> Dr. Sommer schrieb:
>> Sonst kommt die C-Polizei!
>
> Das nicht, aber ein Großteil der Leser wird damit nichts anfangen
> können.

Die C-Polizei lauert hinter jeder Ecke ...

> Du hättest Deinen Beitrag genauso gut in chinesisch posten können.

Ja, das stimmt. Denn die sind Verbesserungen gegenüber sehr 
aufgeschlossen!

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Arduino Fanboy D. schrieb:
> Achim S. schrieb:
>> If(++counter > 59) {counter = 0;}
>
> Das funktioniert nur, wenn man immer, und für alle Zeiten, GARANTIEREN
> kann, dass counter nicht woanders verändert wird.

Das ist jetzt aber ein Allgemeinplatz imho ...

Das meiste funktioniert nur, wenn es nicht woanders verändert wird ;-)

von Dr. Sommer (Gast)


Lesenswert?

Mampf F. schrieb:
> Das meiste funktioniert nur, wenn es nicht woanders verändert wird ;-)

Ein "counter = 72;" ist schnell mal versehentlich getippt. Ein 
"reinterpret_cast<std::uint8_t&> (counter3) = 72;" zur Umgehung des 
Zugriffsschutzes nicht so sehr.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Mampf F. schrieb:
>> Das meiste funktioniert nur, wenn es nicht woanders verändert wird ;-)
>
> Ein "counter = 72;" ist schnell mal versehentlich getippt. Ein
> "reinterpret_cast<std::uint8_t&> (counter3) = 72;" zur Umgehung des
> Zugriffsschutzes nicht so sehr.

Ja, man sollte schon wissen, was man macht ;-)

Passiert selten, dass ich irgendetwas tippe, was ich nicht möchte - im 
Rausch eventuell, aber wenn man wieder nüchtern ist, klärt sich das 
meistens.

von Dr. Sommer (Gast)


Lesenswert?

Mampf F. schrieb:
> Passiert selten, dass ich irgendetwas tippe, was ich nicht möchte

Normal-Intelligenten Programmierern wie mir passiert es leider öfter 
mal, dass man versehentlich was falsches tippt. Das ist der Sinn von 
Sprachen mit Zugriffsschutz (fast alle außer C) und anderen Mechanismen 
mit dem selben Ziel (insb. Typsicherheit) - man wird vor der eigenen 
Unachtsamkeit geschützt, man muss schon mit Absicht diese Mechanismen 
umgehen.

von Peter D. (peda)


Lesenswert?

Arduino Fanboy D. schrieb:
> Achim S. schrieb:
>> If(++counter > 59) {counter = 0;}
>
> Das funktioniert nur, wenn man immer, und für alle Zeiten, GARANTIEREN
> kann, dass counter nicht woanders verändert wird.
>
>> counter = (counter + 1) % 60;
> Ist im dem Punkt erheblich robuster

Warum soll das robuster sein?
Wenn durch einen Programmierfehler ein Wert außerhalb des erlaubten 
Bereiches zugewiesen wurde, ist es herzlich egal, was nun der nächste 
Wert ist. Die Uhr, die FIFO, der gleitende Mittelwert usw. machen in 
beiden Fällen Mumpitz.

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
>> If(++counter > 59) {counter = 0;}
>
> Das funktioniert nur, wenn man immer, und für alle Zeiten, GARANTIEREN
> kann, dass counter nicht woanders verändert wird.

Wenn meine Funktion oben nicht funktioniert, dann must Du definieren, 
welche Arten von Fehlern oder Anwendungsfällen Du zulässt, und zu 
welchem Ergebnis die führen sollen. Denn so pauschal ist Deine 
Schlussfolgerung nicht richtig:

>> counter = (counter + 1) % 60;
> Ist im dem Punkt erheblich robuster

von Wilhelm M. (wimalopaan)


Lesenswert?

Mampf F. schrieb:
> Dr. Sommer schrieb:
>> Mampf F. schrieb:
>>> Das meiste funktioniert nur, wenn es nicht woanders verändert wird ;-)
>>
>> Ein "counter = 72;" ist schnell mal versehentlich getippt. Ein
>> "reinterpret_cast<std::uint8_t&> (counter3) = 72;" zur Umgehung des
>> Zugriffsschutzes nicht so sehr.
>
> Ja, man sollte schon wissen, was man macht ;-)
>
> Passiert selten, dass ich irgendetwas tippe, was ich nicht möchte - im
> Rausch eventuell, aber wenn man wieder nüchtern ist, klärt sich das
> meistens.

Hast Du keine Kollegen?

von Alex W. (a20q90)


Lesenswert?

Jim M. schrieb:
> counter = ++counter % 10;

Jetzt muss ich selber (da ich es nicht ganz verstehe) fragen:

Bedeutet die obige Operation dass der:

a) counter um jeweils 10 erhöht wird

oder

b) um jeweils 1 erhöht wird bis er 10 erreicht und dann 0 wird?

von Dr. Sommer (Gast)


Lesenswert?

Alex W. schrieb:
> Bedeutet die obige Operation dass der:

Diese Operation ist ein Fehler und führt zu beliebigem Verhalten. Keine 
deiner Antworten ist richtig. Wurde doch schon erläutert.

Kaj schrieb:
> Undefined Behavior

von W.S. (Gast)


Lesenswert?

Cman schrieb:
> Wieso ist nochmal so etwas in C nicht gut?
>
> counter = counter++ % 10;
> Danke

Weil du innerhalb einer Berechnung den Wert einer Variable für's 
Ergebnis verwendest und zugleich selbige veränderst.

Also die Regel für's gute Programmieren lautet:

Verändere NIE den Wert einer Variablen innerhalb der Anweisung, wo du 
sie grad verwendest.

Richtig wäre
counter = (counter + 1) % 10;

Bedenke dabei auch mal, daß Modulo eine komplette Division beinhaltet. 
Falls du es einrichten kannst, den zulässigen Bereich auf eine 
Zweierpotenz zu beschränken, dann wäre das Ganze einfacher und schneller 
mit einer Maskierung zu erledigen:
counter = (counter + 1) & 0xF; // zum Beispiel

W.S.

von W.S. (Gast)


Lesenswert?

Rolf M. schrieb:
> ++counter;
> while (counter > 59) {counter -= 60;}
>
> Ich schreibe in so einem Fall die Inkrememntierung eh normalerweise in
> eine eigene Zeile.

Du merkst aber, daß die ganze Diskussion hier ein bissel verkehrt geht. 
Jetzt sind wir nämlich bei Uhrzeiten und bei solchen Dingen ist es 
einfach besser, eben NICHT in Sekunden, Minuten und Stunden zu zählen, 
sondern einfach geradeaus die Zeit in Sekunden (oder wer will, in 
Millisekunden) - und das Darstellen der Uhrzeit Programmteilen zu 
überlassen, die aus einem long, de die Zeit enthält, eine textuelle 
Darstellung in H:M:S zu machen.

W.S.

von Mampf (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Hast Du keine Kollegen?

nicht wenn es ums Programmieren geht - hauptberuflich bin ich Linux 
Admin und die interessanten Sachen mach ich nur nebenbei xD

von Dr. Sommer (Gast)


Lesenswert?

W.S. schrieb:
> und das Darstellen der Uhrzeit Programmteilen zu
> überlassen, die aus einem long, de die Zeit enthält, eine textuelle
> Darstellung in H:M:S zu machen.

Das ist aber langsam und daher für Mikrocontroller ggf. nicht so 
geeignet.

von Wilhelm M. (wimalopaan)


Lesenswert?

Mampf schrieb:
> Wilhelm M. schrieb:
>> Hast Du keine Kollegen?
>
> nicht wenn es ums Programmieren geht - hauptberuflich bin ich Linux
> Admin und die interessanten Sachen mach ich nur nebenbei xD

Dann ist Dir bestimmt auch klar, dass Du auch Dein eigener Kollege sein 
kannst - wenn Du z.B. Deinen eigene Code nach 3 Monaten wieder siehst 
;-)

von HildeK (Gast)


Lesenswert?

Es ist durchaus normal, dass man zuerst an die Modulo-Operation denkt, 
wenn man einen Ringzähler implementieren will. Sie schreibt sich sehr 
übersichtlich und sie funktioniert natürlich auch.
Da sie aber ein richtiges (Modulo-)Ergebnis auch für beliebige 
Eingangswerte liefert, zeigt, dass sie wesentlich mehr macht als für 
einen Ringzähler notwendig ist, wie z.B. für Restklassenmathematik. So 
wird z.B. aus 345 mod 10 eben die 5, bei der if-Abfrage aber nicht. Um 
das zu leisten, kompiliert sie eben auch deutlich größer als die 
if-Abfrage.
Für einen Ringzähler benötigt man nur die effizientere if-Abfrage.

Dr. Sommer schrieb:
> Normal-Intelligenten Programmierern wie mir passiert es leider öfter
> mal, dass man versehentlich was falsches tippt.
Ja, aber dann habe ich einen Fehler in meinem Programm und den sollte 
ich suchen. Da ist es dann auch richtig, wenn mein Programm zunächst 
Mist abliefert und mir den Hinweis gibt, dass noch was im Argen ist.

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


Lesenswert?

Wilhelm M. schrieb:
>> Profis™ machen das so:
>
> Aber Du weißt doch, dass Du in diesem Forum eine C Frage nicht mit C++
> beantworten darfst!

Insbesondere, wenn genau das in der Überschrift steht …

Vom generierten Code her wird es kaum ein Unterschied sein, ob man das 
nun explizit mit einem if testet oder in die Klassendefinition pfercht.

von Dr. Sommer (Gast)


Lesenswert?

HildeK schrieb:
> Ja, aber dann habe ich einen Fehler in meinem Programm und den sollte
> ich suchen

Typische C-Mentalität. Hauptsache der Compiler übersetzt das Programm 
fix ohne zu meckern, damit man es schnell starten kann... und mit der 
Fehlersuche beginnen. Wenn der Fehlerfall aber nur sehr selten eintritt, 
findet man ihn ggf. nicht und liefert ein fehlerhaftes Programm aus. 
Daher sollte man sich die Möglichkeiten einer Hochsprache (hier: C++, 
trifft aber mit unterschiedlichem Level auch auf andere Sprachen zu) zu 
nutze machen und so programmieren, dass der Compiler das Programm 
strenger auf Fehler prüfen kann (hier: Nutzung einer Klasse und 
Zugriffsschutz). So werden eine Menge Fehler sofort erkannt und man 
verschwendet weniger Zeit mit Testen und Debuggen.

von Dr. Sommer (Gast)


Lesenswert?

Jörg W. schrieb:
> Vom generierten Code her wird es kaum ein Unterschied sein, ob man das
> nun explizit mit einem if testet oder in die Klassendefinition pfercht.

Eben drum ist es attraktiv - besserer Schutz vor Fehlern ohne 
Performance-Einbuße.

von Wilhelm M. (wimalopaan)


Lesenswert?

Jörg W. schrieb:
> Wilhelm M. schrieb:
>>> Profis™ machen das so:
>>
>> Aber Du weißt doch, dass Du in diesem Forum eine C Frage nicht mit C++
>> beantworten darfst!
>
> Insbesondere, wenn genau das in der Überschrift steht …

Das ist die Baumarktverkäufermentalität ...

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


Lesenswert?

Wilhelm M. schrieb:
> Jörg W. schrieb:
>> Wilhelm M. schrieb:
>>>> Profis™ machen das so:
>>>
>>> Aber Du weißt doch, dass Du in diesem Forum eine C Frage nicht mit C++
>>> beantworten darfst!
>>
>> Insbesondere, wenn genau das in der Überschrift steht …
>
> Das ist die Baumarktverkäufermentalität ...

Du meinst, der Kunde fragt nach X, und man empfiehlt ihm, dass Y alles 
viel besser kann?  (Obwohl X es durchaus auch könnte)

Ja, da wirst du Recht haben … so gesehen seid ihr hier 
Baumarktverkäufer. :)

: Bearbeitet durch Moderator
von Wilhelm M. (wimalopaan)


Lesenswert?

Jörg W. schrieb:
> Wilhelm M. schrieb:
>> Jörg W. schrieb:
>>> Wilhelm M. schrieb:
>>>>> Profis™ machen das so:
>>>>
>>>> Aber Du weißt doch, dass Du in diesem Forum eine C Frage nicht mit C++
>>>> beantworten darfst!
>>>
>>> Insbesondere, wenn genau das in der Überschrift steht …
>>
>> Das ist die Baumarktverkäufermentalität ...
>
> Du meinst, der Kunde fragt nach X, und man empfiehlt ihm, dass Y alles
> viel besser kann?  (Obwohl X es durchaus auch könnte)

Wo steht der Baumarkt mit so einem Verkäufer? Da würde ich gerne mal 
hin!

Ich würde mich sehr freuen über: "X kann es, aber mit folgenden 
Nachteilen. Ich empfehle aber Y, weil es folgende Vorteile hat".

Anstatt zu hören: "Ja, nimm X. Was anderes gibt es nicht und wir haben 
das immer so gemacht."

von W.S. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Das ist aber langsam und daher für Mikrocontroller ggf. nicht so
> geeignet.

Nö. Überhaupt nicht.

Bedenke mal, daß das schlichte Hochzählen der Uhrzeit im Timertick alle 
1 oder 10 ms erfolgt, eine eventuelle Darstellung als Text in einem 
Ausdruck oder Display jedoch nur dann, wenn der betreffende Inhalt 
aufgebaut wird, also im menschlichen Maße von nicht schneller als einige 
100 ms.

Und da wäre nochwas zur Bilanz:

Auch dann, wenn du sek,min,hr bereits als einzelne Variablen hättest, 
würdest du zwecks Darstellung als 10:09:53 jedesmal eine 
Ausgabekonvertierung benötigen, die wiederum mehrere Divisionen braucht. 
Da ist es wesentlich einfacher und schneller und platzsparender, sowohl 
die Division als auch Modulo mit ein paar ldiv's aus der Uhrzeit im long 
zu erledigen.

W.S.

von Dr. Sommer (Gast)


Lesenswert?

W.S. schrieb:
> Bedenke mal, daß das schlichte Hochzählen der Uhrzeit im Timertick alle
> 1 oder 10 ms erfolgt

Wenn das denn so ist, und nicht irgendeine andere Form der (schnellen) 
Simulation o.ä. Hardware-RTC's zählen übrigens auch die Sekunden, 
Minuten, Stunden einzeln hoch, und zwar jede Dezimal-Ziffer einzeln. Das 
wird auch einen Grund haben.

W.S. schrieb:
> platzsparender
Wenn man eine Routine für long-Division im Code hat? Die ist bestimmt 
länger als ein paar bedingte Blöcke.

von Roland F. (rhf)


Lesenswert?

Hallo,
Wilhelm M. schrieb:
> Ich würde mich sehr freuen über: "X kann es, aber mit folgenden
> Nachteilen. Ich empfehle aber Y, weil es folgende Vorteile hat".

Ja, genau.
Ich stelle mir gerade vor wie ein Kunde, der von einem Holzbrett eine 
Stück absägen will, gezielt nach einer passenden Säge fragt und vom 
Baumarktmitarbeiter gesagt bekommt, das er doch besser in einen 
CNC-Holz-Hobel-Bohr-Sägen-Fräsen-Schleifer nebst 1-wöchigem 
Bediengrundkurs investieren soll.
Obwohl es auch ein Billigfuchsschwanz aus der Grabbeltheke getan hätte.

rhf

P.S.:
Wenn ich mir hier manchmal so die "Vereinfachungen" die durch den 
Gebrauch von "geeigneteren" Programmiersprachen als C ansehe, überkommt 
mich eine ungutes Gefühl.

von Dr. Sommer (Gast)


Lesenswert?

Roland F. schrieb:
> das er doch besser in einen
> CNC-Holz-Hobel-Bohr-Sägen-Fräsen-Schleifer nebst 1-wöchigem
> Bediengrundkurs investieren soll.

Im Gegensatz zu echten Werkzeugen kostet die Nutzung von Klassen und 
Kapselung kein Geld. C++-Compiler sind für viele Plattformen gratis/open 
source verfügbar.

Roland F. schrieb:
> P.S.:
> Wenn ich mir hier manchmal so die "Vereinfachungen" die durch den
> Gebrauch von "geeigneteren" Programmiersprachen als C ansehe, überkommt
> mich eine ungutes Gefühl.

Angst, was zu verpassen? Ineffizienter als andere zu arbeiten?

Beitrag #5622761 wurde von einem Moderator gelöscht.
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Im Gegensatz zu echten Werkzeugen kostet die Nutzung von Klassen und
> Kapselung kein Geld.

Sie ist aber auch nicht "for free" zu haben: die dahinter liegenden 
Konzepte zu verstehen, braucht mehr Einarbeitungsaufwand. Im 
kommerziellen Umfeld ist Zeit letztlich auch Geld. Wenn ich sowas nur 
einmal für eine simple Uhr brauche, wird sich das kaum lohnen, wenn ich 
das wirklich immer wieder verwenden kann, ist das was anderes.

von Dr. Sommer (Gast)


Lesenswert?

Jörg W. schrieb:
> wenn ich
> das wirklich immer wieder verwenden kann, ist das was anderes.

Mechanismen zur Abstraktion und Kapselung kann man für alle Arten der 
Programmierung nutzen, nicht nur für eine Uhr. Daher lohnt sich die 
Einarbeitungszeit mehrfach.

Jörg W. schrieb:
> Wenn ich sowas nur
> einmal für eine simple Uhr brauche
Wie wahrscheinlich ist es, dass man im kommerziellen Umfeld einmal so 
ein Massenprodukt wie eine Uhr programmiert, und dann nie wieder 
etwas...

Wenn man direkt eine High-Level-Sprache statt C lernen würde (z.B. Java 
oder Python), wäre der Einarbeitungsaufwand sowieso gering, da kommen 
solche Dinge ganz natürlich.
Und wer weiß, vielleicht lernt man ja sogar schneller wenn man erst 
grundlegende Prinzipien mit Python lernt, und dann für Controller auf 
C++ umsteigt, anstatt sich sofort mit den Eigenheiten des letztgenannten 
herumschlagen zu müssen...

von Roland F. (rhf)


Lesenswert?

Hallo,
Dr. Sommer schrieb:
> Im Gegensatz zu echten Werkzeugen kostet die Nutzung von Klassen und
> Kapselung kein Geld.

Und die permanente Einarbeitung in immer komplexere Abstraktionsebenen 
un  immer komplexere Sprachmittel ist kostenlos?
Und welche Abstraktionsebene und welches Sprachmittel ist eigentlich das 
Beste?
Und sind auch alle Programmierer auf dem neuesten Stand und beherrschen 
all diese Werkzeuge?

> Angst, was zu verpassen? Ineffizienter als andere zu arbeiten?

Ich bin in der glücklichen Lage weder mit Elektronik noch mit 
Softwareerstellung beruflich zu tun zu haben, für mich ist das alles nur 
Hobby.
Aber wenn ich dann hier lese wie aus
1
counter = counter++ % 10;

über
1
counter = (counter + 1) % 10;

dann so was
1
template <typename T, T Max>
2
class Counter {
3
  public:
4
    constexpr Counter (T v = 0) : value (v) {}
5
    operator T () const { return value; }
6
    T get () const { return value; }
7
    Counter& count () { if (++value == Max) value = 0; return *this; }
8
  private:
9
    T value;
10
};
11
12
int main () {
13
  Counter<uint8_t, 3> counter3;
14
  
15
  for (std::int8_t i = 0; i < 10; ++i)
16
    std::cout << int { counter3.count () } << std::endl;
17
}

wird, stelle ich mir die Frage ob das wirklich nötig ist. Nicht alles 
was möglich ist, ist auch sinnvoll.

rhf

P.S.:
Vor einiger Zeit habe ich mal gelesen das Linus Torvalds wohl weiterhin 
darauf besteht das der Linux-Kernel in C geschrieben wird. Langsam wird 
mir klar warum.

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


Lesenswert?

Dr. Sommer schrieb:
> Wenn man direkt eine High-Level-Sprache statt C lernen würde (z.B. Java
> oder Python), wäre der Einarbeitungsaufwand sowieso gering, da kommen
> solche Dinge ganz natürlich.

Trotzdem kannst du das nicht vergleichen. Ich bin mir ziemlich sicher, 
dass keiner unserer Python-schreibenden und C-kennenden Programmierer 
(mich eingeschlossen :) in der Lage wäre, das in C++ passend aus dem 
Stegreif zu formulieren, ohne es irgendwo erstmal nachlesen zu gehen. 
Die Syntax ist halt eine reichlich andere, es hilft dir da nicht viel, 
die zugrunde liegenden Konzepte zu kennen.

von Roland F. (rhf)


Lesenswert?

Hallo,
Dr. Sommer schrieb:
> Und wer weiß, vielleicht lernt man ja sogar schneller wenn man erst
> grundlegende Prinzipien mit Python lernt, und dann für Controller auf
> C++ umsteigt, anstatt sich sofort mit den Eigenheiten des letztgenannten
> herumschlagen zu müssen...

Erinnert mich an meine Schulzeit, als uns mal ein Lehrer erklärt hat das 
es viel besser wäre sich erst einmal intensiv mit Latein und Griechisch 
zu beschäftigen, danach könnte man alle anderen Sprachen spielend 
einfach lernen. Wir wollten aber eigentlich nur Englisch sprechen und 
lesen können...

rhf

von Wilhelm M. (wimalopaan)


Lesenswert?

Jörg W. schrieb:
> Dr. Sommer schrieb:
>> Wenn man direkt eine High-Level-Sprache statt C lernen würde (z.B. Java
>> oder Python), wäre der Einarbeitungsaufwand sowieso gering, da kommen
>> solche Dinge ganz natürlich.
>
> Trotzdem kannst du das nicht vergleichen. Ich bin mir ziemlich sicher,
> dass keiner unserer Python-schreibenden und C-kennenden Programmierer
> (mich eingeschlossen :) in der Lage wäre, das in C++ passend aus dem
> Stegreif zu formulieren, ohne es irgendwo erstmal nachlesen zu gehen.
> Die Syntax ist halt eine reichlich andere, es hilft dir da nicht viel,
> die zugrunde liegenden Konzepte zu kennen.

So ein kleines Template wie das obige, um bspw. einen saturierenden 
ganzzahligen, numerischen DT zu modellieren, lernt man als Studierender 
auf einer vernünftigen heutigen Hochschule im BA-Informatik im 2. 
Semester.

Aber viel wichtiger ist es sich klar zu machen, dass die primitiven DT 
entweder als das genutzt werden sollen, was sie darstellen, oder man 
sich andernfalls eigene DT schafft, um das zu modellieren, was man 
modellieren will.

von Dr. Sommer (Gast)


Lesenswert?

Roland F. schrieb:
> Und die permanente Einarbeitung in immer komplexere Abstraktionsebenen
> un  immer komplexere Sprachmittel ist kostenlos?

Nein, aber zahlt sich aus in der eingesparten Zeit der Fehlersuche.

Roland F. schrieb:
> Und welche Abstraktionsebene und welches Sprachmittel ist eigentlich das
> Beste?
Das ist schwierig zu beantworten und hängt stark von der Anwendung ab. 
Allgemein ist OOP extrem verbreitet und für vieles geeignet. Im 
Embedded-Bereich hat sich erfahrungsgemäß ein "wenig OOP" mit einfachen 
Patterns wie "Observer" und "State", und natürlich wie hier zur 
Datenkapselung, als gut bewiesen. Fortgeschrittene Programmierer können 
hier noch von der Metaprogrammierung profitieren, da sie Effizienz & 
Abstraktion kombiniert. Teilweise sind auch 
Pipes&Processors-Architekturen sinnvoll; Simulink z.B. macht nichts 
anderes.

Roland F. schrieb:
> wird, stelle ich mir die Frage ob das wirklich nötig ist. Nicht alles
> was möglich ist, ist auch sinnvoll.
Die Klassendefinition schreibt man genau 1x und verpackt sie in eine 
Bibliothek, oder nutzt eine fertige. Danach sieht man nur noch:
1
Counter<uint8_t, 3> counter3;
2
counter3.count ();
Btw, kleiner Nebeneffekt: Wenn man an verschiedenen Stellen zählt, muss 
man nicht jedes Mal das Maximum (3) wiederholen, man kann es an 
zentraler Stelle konfigurieren.

Roland F. schrieb:
> Vor einiger Zeit habe ich mal gelesen das Linus Torvalds wohl weiterhin
> darauf besteht das der Linux-Kernel in C geschrieben wird. Langsam wird
> mir klar warum.
Hauptsächlich weil es damals keine guten C++-Compiler gab. Wenn man sich 
den Linux Source-Code so anschaut, fragt man sich warum man auf Biegen 
und Brechen in C Dinge tun muss, für die es in C++ explizit bessere 
Mittel gibt.

Jörg W. schrieb:
> Die Syntax ist halt eine reichlich andere, es hilft dir da nicht viel,
> die zugrunde liegenden Konzepte zu kennen.
Aber sie lernt sich schnell wenn man die Konzepte kennt. Wie gesagt 
lohnt sich die Lern-Zeit. Oder würdest du auf die Nutzung eines CAD 
verzichten und lieber mit Stift&Papier layouten, weil das Lernen des CAD 
so lange dauert?

Roland F. schrieb:
> danach könnte man alle anderen Sprachen spielend
> einfach lernen. Wir wollten aber eigentlich nur Englisch sprechen und
> lesen können...
Wenn Latein & Griechisch viel einfacher und schneller lernbarer wären 
als Englisch, wäre dein Vergleich sinnvoll.

von C-Laie (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Das funktioniert nur, wenn man immer, und für alle Zeiten, GARANTIEREN
> kann, dass counter nicht woanders verändert wird.

Kann man das dann nicht einfach "einkapseln"?
1
int TimerTick(void) {
2
static seconds =0;
3
4
  seconds++;
5
  if (seconds >59) seconds=0;
6
7
  return seconds;
8
9
}

Wilhelm M. schrieb:
> So ein kleines Template wie das obige, um bspw. einen saturierenden
> ganzzahligen, numerischen DT zu modellieren, lernt man als Studierender
> auf einer vernünftigen heutigen Hochschule im BA-Informatik im 2.
> Semester.

Du meinst ich muss ein Informatikstudium machen um einen Sekundenzähler 
zu proggen? ;-)

von Dr. Sommer (Gast)


Lesenswert?

C-Laie schrieb:
> Kann man das dann nicht einfach "einkapseln"?

Und was wenn du mehr als 1 Zähler brauchst? Von einer statischen 
Variable gibt es immer nur genau eine...

von Wilhelm M. (wimalopaan)


Lesenswert?

C-Laie schrieb:
> Kann man das dann nicht einfach "einkapseln"?
>
>
1
> int TimerTick(void) {
2
> static seconds =0;
3
>   seconds++;
4
>   if (seconds >59) seconds=0;
5
>   return seconds;
6
> }
7
>
>
>
> Du meinst ich muss ein Informatikstudium machen um einen Sekundenzähler
> zu proggen? ;-)

Wenn Du Deine obige "Lösung" als richtig ansiehst, dann ja.

von Axel S. (a-za-z0-9)


Lesenswert?

W.S. schrieb:
>Dr. Sommer schrieb:
>> W.S. schrieb:
>>> und das Darstellen der Uhrzeit Programmteilen zu
>>> überlassen, die aus einem long, de die Zeit enthält, eine textuelle
>>> Darstellung in H:M:S zu machen.

>> Das ist aber langsam und daher für Mikrocontroller ggf. nicht so
>> geeignet.
>
> Nö. Überhaupt nicht.

Aber hallo. Die Umrechnung von Sekunden, womöglich noch Sekunden seit 
dem Epoch (UNIXTIME) in HH:MM:SS ist aufwendig. Ohne Division und 
Modulo-Operation würde man das nicht schreiben wollen.

Die Komponenten einfach zu inkrementieren und den Überlauf per if() zu 
fangen, ist da deutlich weniger aufwendig.

> Bedenke mal, daß das schlichte Hochzählen der Uhrzeit im Timertick alle
> 1 oder 10 ms erfolgt, eine eventuelle Darstellung als Text in einem
> Ausdruck oder Display jedoch nur dann, wenn der betreffende Inhalt
> aufgebaut wird, also im menschlichen Maße von nicht schneller als einige
> 100 ms.

Das ist gleich doppelt falsch. Zum einen war bisher noch gar nicht die 
Rede davon, daß es ein Inkrement der Zeit häufiger als einmal pro 
Sekunde geben würde. Für ein Programm, das die Uhrzeit in irgendeiner 
Form anzeigt, braucht man die Formatierung als HH:MM:SS aber bei jedem 
Inkrement. Das Aufschieben der Umrechnung spart dann gar nichts ein.

Zum zweiten muß ich dir jetzt deine eigene Argumentation entgegen 
halten: wenn der Interrupt jede Millisekunde kommt, dann kannst du doch 
genausogut einen großen Millisekundenzähler inkrementieren und die 
Umrechnung desselben in Sekunden, Minuten usw. einfach an eine höhere 
Schicht delegieren. Macht aber kein Mensch so. Statt dessen wird man im 
Interrupt einen lokalen Zähler bis 1000 (bei 1ms Intervall) zählen 
lassen und bei dessen Überlauf den Sekundenzähler (bzw. die Zeit-struct) 
inkrementieren. Mit anderen Worten: man macht genau jene Operation, die 
du bei den Sekunden verteufelst, für den Millisekundenzähler.

> Auch dann, wenn du sek,min,hr bereits als einzelne Variablen hättest,
> würdest du zwecks Darstellung als 10:09:53 jedesmal eine
> Ausgabekonvertierung benötigen, die wiederum mehrere Divisionen braucht.

Keineswegs. Eine zweistellige Dezimalzahl kann man auch ohne Divisionen 
nach ASCII konvertieren. Einen 32-bittigen Sekundenzähler in Sekunden, 
Minuten und Stunden zu zerlegen - das will man nicht ohne Division 
machen.

Und wenn man auch die letzten paar Zyklen einsparen will, dann speichert 
und rechnet man Sekunden, Minuten und Stunden als gepackte BCD-Zahlen.

von Roland F. (rhf)


Lesenswert?

Hallo,
Dr. Sommer schrieb:
> Die Klassendefinition schreibt man genau 1x und verpackt sie in eine
> Bibliothek, oder nutzt eine fertige. Danach sieht man nur noch:
>
1
Counter<uint8_t, 3> counter3;
2
> counter3.count ();

Prima, jetzt hast du eine universell nutzbare Klasse. Wenn man das jetzt 
für jedes "Problem" macht, hat man doch irgend eine ungeheuer große 
Anzahl an universell einsetzbaren Klassen. Wie behält man da den 
Überblick? Kannst du dich auch in ein paar Jahren nach erinnern und 
findest die damalige Lösung sofort wieder?
Und vielleicht ist die Klasse doch nicht so universell einsetzbar und 
man muss wieder eine eine neue Klasse entwerfen, die dann wiederum von 
anderen Basisklassen abhängt, deren Funktionsweise man erst mal 
verstehen muss.
Ich könnte mir vorstellen, das es da viel einfacher ist statt immer 
weiter zu abstrahieren das "Problem" einfach mal einfach anzugehen. 
Insbesonders wenn es sich, wie im Ausgangsbeitrag, um ein eher triviales 
"Problem" handelt.
Verstehe mich nicht falsch, die von dir beschriebene Vorgehensweise ist 
sicherlich bei umfangreicher und komplexer Software sinnvoll. Aber alles 
und jedes zu abstrahieren weil es ja vielleicht, möglicherweise, 
eventuell nochmal woanders Verwendung findet, scheint mir nicht sehr 
sinnvoll zu sein.

rhf

von HyperMario (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Und was wenn du mehr als 1 Zähler brauchst? Von einer statischen
> Variable gibt es immer nur genau eine...

und was mache ich wenn ich eine Mondrakete brauche? Wäre da (Hier die 
LieblingsProgrammierSprache einsetzen) nicht auch überfordert? ;-)

von Dr. Sommer (Gast)


Lesenswert?

Roland F. schrieb:
> end eine ungeheuer große
> Anzahl an universell einsetzbaren Klassen. Wie behält man da den
> Überblick?

Mit einer vernünftigen Dokumentation. Geht bei den riesigen Bibliotheken 
von Java oder .Net ja auch.

Genau so eine Counter-Klasse habe ich übrigens in mehreren Projekten im 
Einsatz, mit noch ein paar weiteren Funktionen. Es ist enorm praktisch, 
den maximalen Zählerstand zentral konfigurieren zu können. Daher ja, es 
ist sinnvoll so einfache Dinge zu kapseln. Viele der Algorithmen in 
der C++-Standardbibliothek sind auch nicht besonders komplex; aber 
dennoch ist es praktisch, sie nutzen zu können.
Das Hauptargument für Simulink beispielsweise ist, dass es vorgefertigte 
Komponenten für Verzögerungsglieder, Hysteresen, Filter... hat. Die sind 
für sich genommen auch alle relativ simpel, aber dennoch schwören viele 
darauf. Das kann man doch in C++ auch so machen. Man muss das Rad nicht 
ständig neu erfinden.

HyperMario schrieb:
> und was mache ich wenn ich eine Mondrakete brauche? Wäre da (Hier die
> LieblingsProgrammierSprache einsetzen) nicht auch überfordert? ;-)
Ja, deswegen wird da Ada verwendet. Das ist ähnlich komplex wie C++, ist 
aber noch strikter und führt genau die Paradigmen, die ich angesprochen 
habe (Typsicherheit, Kapselung) noch weiter aus.

von 900ss (900ss)


Lesenswert?

Dr. Sommer schrieb:
> für die es in C++ explizit bessere Mittel gibt.

Das mag sein. C++ war hier aber nirgends gefordert. Und die Diskussion 
driftet wie schon des öfteren ab.

Mach doch einen neuen Tread auf für das Thema in C++.

C-Polizei? Nein es hat da nichts mit zu tun. Es wird schlicht am Thema 
vorbei diskutiert. Thema verfehlt, 6, setzen ;)

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Baumarktverkäufer eben. :-)

von 900ss (900ss)


Lesenswert?

Schöner Vergleich. Und wie gut der zutrifft :-)

von Wilhelm M. (wimalopaan)


Lesenswert?

900ss D. schrieb:
> Schöner Vergleich. Und wie gut der zutrifft :-)

Genau, der Kunde bekommt, was er will, und nicht das, was er braucht.

von CaptainA (Gast)


Lesenswert?

Jetzt geht mir ein Licht auf, warum es bisher nicht geklappt hat, die 
Uhrzeit auf Dezimalsystem umzustellen. Man sollte sie auf binär 
umstellen.

1 Tag = 32 Stunden á 64 Minuten á 64 Sekunden = 65536 Sekunden.

Das weicht gar nicht mal so stark von unserem aktuellen Empfinden ab. 
Stunden und Minuten vergehen ca. 24% schneller, die Sekunde gut 32% 
schneller. Da gewöhnt man sich dran !

Und man kann super effizient mit AND und SHIFT rechnen.

;-)

von Axel S. (a-za-z0-9)


Lesenswert?

CaptainA schrieb:
> 1 Tag = 32 Stunden á 64 Minuten á 64 Sekunden = 65536 Sekunden.

Hat was. Die 64 = 8·8 kann man gut an 8 Fingern abzählen.
Einfach die Daumen abhacken. Die taugen eh zu nix ;)

von CaptainA (Gast)


Lesenswert?

Ich will nicht vom eigentlich Thema zu weit abschweifen. Aber die Daumen 
sind es doch, die uns vom Känguru unterscheiden.

von Egon D. (Gast)


Lesenswert?

Wilhelm M. schrieb:

> Peter D. schrieb:
>> Dr. Sommer schrieb:
>>> Sonst kommt die C-Polizei!
>>
>> Das nicht, aber ein Großteil der Leser wird
>> damit nichts anfangen können.
>
> Die C-Polizei lauert hinter jeder Ecke ...

Die sollte noch viel schärfer durchgreifen, denn
diese penetrante C++-Missioniererei in aber wirklich
JEDEM C-Thread nervt ganz gewaltig.

von Rainer V. (a_zip)


Lesenswert?

Hallo, nachdem sich die ganze Geschichte wieder einmal zu einem kleinen 
Glaubenskrieg entwickelt hat, frage ich einfach mal, wer denn zum Teufel 
schreibt sowas in C ??? Dachte wir reden über Ćontroller und da ist erst 
in der hohen Liga an C, oder... zu denken. Auf meinem AVR mach ich doch 
sowas nicht?!!!
OK, die "Zusammenklick-Fraktion" aber sonst? Und das aufgekommenen 
Beispiel mit Uhr (HH:MM:SS), das macht man doch nicht in einer 
Hochsprache. Da ist genau Packed-BCD angesagt...
Gruß und viel Spass, Rainer

von Egon D. (Gast)


Lesenswert?

Rainer V. schrieb:

> frage ich einfach mal, wer denn zum Teufel schreibt
> sowas in C ???

Jeder, der mehr als eine Controllerfamilie verwendet.


> Dachte wir reden über Ćontroller und da ist erst
> in der hohen Liga an C, oder... zu denken.

Wie kommst Du darauf?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Rainer V. schrieb:
> Auf meinem AVR mach ich doch sowas nicht?!!!

Wenn Dein AVR einer der ganz, ganz winzkleinen Tinys ist, dann kann man 
darauf kein C verwenden, aber auf jedem anderen sehr wohl, und das 
geht bestens. Auch schon auf einem etwas größeren Tiny wie z.B. dem 
Tiny85 (auf dem kann man sogar C++ einsetzen, wie es im Arduino-Umfeld 
üblich ist).

von Rainer V. (a_zip)


Lesenswert?

Egon D. schrieb:
> Jeder, der mehr als eine Controllerfamilie verwendet.

Sorry, aber ich dachte wir sprechen über "Bastler".
Und ein Profibereich, wo irgendwas für mehrere Controllerfamilien 
gebastelt wird, ist mir "neu"...bzw. ehr unbekannt. Egon könnte sich 
aber durchaus am berühmten "Siemensfenster" befinden, und dort werden 
wahrscheinlich portable Klassen für jeden erdenklichen Unsinn 
geschrieben. Sorry, sollte nicht persönlich werden, ist es aber...
Gruß Rainer

von W.S. (Gast)


Lesenswert?

Roland F. schrieb:
> Erinnert mich an meine Schulzeit, als uns mal ein Lehrer erklärt hat das
> es viel besser wäre sich erst einmal intensiv mit Latein und Griechisch
> zu beschäftigen, danach könnte man alle anderen Sprachen spielend
> einfach lernen. Wir wollten aber eigentlich nur Englisch sprechen und
> lesen können...

Das läuft auf die Frage hinaus "Wozu brauch ich Bildung?"

..und abgesehen davon versteht man mit etwas Latein im Kreuz auch 
Englisch deutlich besser als ohne, dito französisch, dito sogar deutsch.

W.S.

von A. S. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Hauptsächlich weil es damals keine guten C++-Compiler gab. Wenn man sich
> den Linux Source-Code so anschaut, fragt man sich warum man auf Biegen
> und Brechen in C Dinge tun muss, für die es in C++ explizit bessere
> Mittel gibt.

Nein. Es geht nicht um die Compiler! Z.B.: 
http://harmful.cat-v.org/software/c++/linus

Es geht um die Mentalität der Programmierer und letztendlich um die 
Lesbarkeit des Codes.

Dr. Sommer schrieb:
> Ja, deswegen wird da Ada verwendet.

... und noch öfter C. Natürlich mit entsprechender statischer und 
dynamischer Analyse etc, genauer gesagt: mit allen Analysetools.

Roland F. schrieb:
> Verstehe mich nicht falsch, die von dir beschriebene Vorgehensweise ist
> sicherlich bei umfangreicher und komplexer Software sinnvoll.

Eher: Ein notwendiges Übel um sauber zu bleiben.

> Aber alles
> und jedes zu abstrahieren weil es ja vielleicht, möglicherweise,
> eventuell nochmal woanders Verwendung findet, scheint mir nicht sehr
> sinnvoll zu sein.
Vor allem führt es direkt zu Unit-Tests. Es ist nichts falsch mit 
Unit-Tests, aber insgesamt führt es zu hunderten kleinen Routinen, 
Codeschnippseln, die alle getestet sind, 100% Pfad- und Code- und 
Branch- und wasfürabdeckung. Man kreiert ein eigenes Sprachuniversum, 
dass völlig o.k. ist, wenn es von 1000en genutzt wird und es eine 
Dokumentation gibt, wie Dr. Sommer selbst schreibt:

Dr. Sommer schrieb:
> Mit einer vernünftigen Dokumentation. Geht bei den riesigen Bibliotheken
> von Java oder .Net ja auch.

Aber in meinem Universum von 2, 10 oder 20 Entwicklern ist ein Überblick 
per parallel gepflegter Doku (auch wenns Doxygen ist) ein Misstand.

Bei einer API, OK, bei Minifunktionen: Nein.

von Rainer V. (a_zip)


Lesenswert?

W.S. schrieb:
> ..und abgesehen davon versteht man mit etwas Latein im Kreuz auch
> Englisch deutlich besser als ohne, dito französisch, dito sogar deutsch.

Full agree...und italiänisch, und spanisch und und und,
ich hatte zwar nur eine "4" in Latein, aber das hilft für alle 
"romanischen" Sprachen! Und dann gleich noch die ähnlich (sinnfreie) 
Frage: wozu soll ich Mathe lernen.
Ja,Ja...
Gruß Rainer

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Rainer V. schrieb:
> Sorry, aber ich dachte wir sprechen über "Bastler".

Auch die haben in den letzten Jahrzehnten den Gebrauch anderer 
Programmiersprachen als Assembler durchaus kennengelernt, und sie sind 
gerade dadurch nicht mehr so sehr an die eine Controllerfamilie 
gebunden, mit der sie angefangen haben.

Die große Arduinofraktion beispielsweise kommt mit AVRs, ARMen, 
irgendwelchen Expressif-Kernen (ESP8266 etc.) und (wenn man "Arduino" 
durch das kompatible "Energia" ersetzt) auch MSP430, C2000 etc. ohne 
größere Probleme zurecht.

Und das sind Bastler.

von Egon D. (Gast)


Lesenswert?

Rainer V. schrieb:

> Egon D. schrieb:
>> Jeder, der mehr als eine Controllerfamilie verwendet.
>
> Sorry, aber ich dachte wir sprechen über "Bastler".

Wo nimmst Du das her? Es ging um eine C-Frage.


> Und ein Profibereich, wo irgendwas für mehrere
> Controllerfamilien gebastelt wird, ist mir "neu"...
> bzw. ehr unbekannt.

Außer Klitschen, die ausschließlich eigene Geräte
entwickeln, hat meiner Erfahrung nach niemand den
Luxus, sich die Controllerfamilie in jedem Falle
aussuchen zu können.
Und da man nicht jedesmal das Rad in Assembler neu
erfinden will, wird eben die einzige "Hochsprache"
verwendet, die auf praktisch jedem Controller
verfügbar ist...


> Egon könnte sich aber durchaus am berühmten
> "Siemensfenster" befinden, und dort werden
> wahrscheinlich portable Klassen für jeden
> erdenklichen Unsinn geschrieben.

Klassen in C? Verwechselst Du da nicht gerade
etwas?

von Rainer V. (a_zip)


Lesenswert?

Rufus Τ. F. schrieb:
> Und das sind Bastler.

Ich gebe dir voll Recht, aber die diversen Fragen, nicht nur hier im 
Forum, lassen mich an Vielem zweifeln...

Egon D. schrieb:
> Wo nimmst Du das her? Es ging um eine C-Frage.

OK, habe mich zu weit herausgehängt...trotzdem scheint mir die Frage, 
wie der eines Erstklässlers, der verzweifelt seine Schultüte sucht...
Gruß Rainer

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Rainer V. schrieb:
> aber die diversen Fragen, nicht nur hier im Forum, lassen mich an Vielem
> zweifeln...

Das ist etwas, was Dir unbenommen ist.

Nur: Der Bastler hat sich seit den 80ern stark verändert; wer damals 
froh um jeden Informationsfitzel war, den er irgendwo ergattern konnte 
und Datenbücher & Datenblätter gesammelt hat (und als Einschlafliteratur 
nutzte), wer also nicht auf die allumfassende Informationsquelle 
"Internet" zugreifen konnte, der hat eine komplett andere 
Herangehensweise an die Materie als derjenige, der heute mit einer 
unglaublichen Vielzahl phantastisch leistungsfähiger, spottbilliger und 
mit Unmengen an Dokumentation, Beispielcode, Entwicklungssystemen etc. 
ausgestatteten Systemen konfrontiert ist.

Und ja, auch damals, als Bastler in den 80ern, hat man in der Lernphase 
Verständnisprobleme und komplett unrealistische Ideen gehabt, die früher 
oder später beim harten Kontakt mit der Realität starben (ich kann mich 
erinnern, als Schüler mal die Idee gehabt zu haben, daß man ja auch 'nen 
stinknormalen Audiocassettenrecorder nutzen könnte, um damit Videos 
aufzunehmen -- ich wusste damals halt nicht wirklich viel bzw. eher 
überhaupt nichts darüber, was "Video" eigentlich ist). Heute, wo jede 
Idee, jede Frage sofort ins Internet gestopft wird, wird so etwas 
natürlich augenscheinlicher.

Das aber ist dann auch schon der große Unterschied.

Daß damals viele Bastler auch keinerlei Grundlagenwissen hatten, fiel 
nicht so sehr auf, weil sie mit ihren Fragen nicht die Reichweite 
hatten, die heute das Internet bietet.

von Egon D. (Gast)


Lesenswert?

Rainer V. schrieb:

> Egon D. schrieb:
>> Wo nimmst Du das her? Es ging um eine C-Frage.
>
> OK, habe mich zu weit herausgehängt...trotzdem
> scheint mir die Frage, wie der eines Erstklässlers,
> der verzweifelt seine Schultüte sucht...

Wessen Frage? Die des TO?

Ich finde die Frage eigentlich berechtigt, denn es ist
nach meinem Empfinden überhaupt nicht offensichtlich,
dass "counter++" nicht für "(counter+1)" steht, sondern
für "counter = (counter+1)".

Diese verdeckte Zuweisung ist halt eine der unzähligen
Fallen in C, aber daraus zu folgern, dass man C nicht
einsetzen sollte, hieße, das Kind mit dem Bade auszu-
schütten.
Es genügt ja völlig, wenn man MISRA folgt und die
Operatoren "++" und "--" nicht zusammen mit anderen
Operatoren in ein und demselben Ausdruck verwendet.

Man muss ja nicht gleich so weit gehen wie ich und
"++" bzw. "--" gar nicht mehr einsetzen...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Egon D. schrieb:
> denn es ist nach meinem Empfinden überhaupt nicht offensichtlich, dass
> "counter++" nicht für "(counter+1)" steht, sondern für "counter =
> (counter+1)".


Du hast also in C noch nie eine auf die übliche Art und Weise 
formulierte for - Schleife gesehen?
1
for (i = 0; i < 10; i++)
2
{
3
}

Ich fände es hochgradig unoffensichtlich, stünde x++ für den Ausdruck "x 
+ 1".

Damit würde vor allem die Schleife irgendwie nicht funktionieren.

von Egon D. (Gast)


Lesenswert?

Rufus Τ. F. schrieb:

> Egon D. schrieb:
>> denn es ist nach meinem Empfinden überhaupt nicht
>> offensichtlich, dass "counter++" nicht für "(counter+1)"
>> steht, sondern für "counter = (counter+1)".
>
> Du hast also in C noch nie eine auf die übliche Art
> und Weise formulierte for - Schleife gesehen?

Doch, natürlich -- aber wer sagt Dir, dass ich die nicht
genauso beschissen finde?


> for (i = 0; i < 10; i++)
> {
> }

Ja... das sieht in Tcl exakt genauso aus (glaube ich).

Gottseidank habe ich den Luxus, in 90% aller Fälle einfach
1
 
2
foreach ding $dingliste { 
3
...
4
}
schreiben zu können, und in den restlichen 9.99% schreibe ich
1
set i 0 
2
while { $i < 10 } { 
3
...
4
incr i 
5
}

Die einzige Falle hierbei besteht darin, das "incr i" nicht
zu vergessen, aber das nehme ich gern in Kauf.

Ich greife ja niemanden an, der meine speziellen Abneigungen
nicht teilt -- aber ich nehme mir im Gegenzug die Freiheit,
die Operatoren mit Seiteneffekt wie auch die Tatsache, dass
Zuweisungen AUSDRÜCKE sind (und keine Anweisungen) zum
kränkesten zu zählen, was C zu bieten hat.

von Rainer V. (a_zip)


Lesenswert?

Rufus Τ. F. schrieb:
> Du hast also in C noch nie eine auf die übliche Art und Weise
> formulierte for - Schleife gesehen?

Liebe Leute, ok, es geht natürlich weiter...demnächst werden wir noch 
über eine reine Constanten- oder Variablen-Def. in C diskutieren...ist 
doch blöd oder..
Gruß Rainer

von Egon D. (Gast)


Lesenswert?

Rainer V. schrieb:

> Liebe Leute, ok, es geht natürlich weiter...demnächst
> werden wir noch über eine reine Constanten- oder
> Variablen-Def. in C diskutieren...ist doch blöd oder..

???

Warum beteiligst Du Dich an einem C-Thread, wenn Dich
C nicht interessiert?

Ich bin dabei, meinen Horizont von Assembler, Pascal
und Tcl auf C auszudehnen, und ich finde Diskussionen,
was man in C tun und lassen sollte, ziemlich nützlich.

Wo liegt Dein Problem?

von Rainer V. (a_zip)


Lesenswert?

Egon D. schrieb:
> Warum beteiligst Du Dich an einem C-Thread, wenn Dich
> C nicht interessiert?
>
> Ich bin dabei, meinen Horizont von Assembler, Pascal
> und Tcl auf C auszudehnen, und ich finde Diskussionen,
> was man in C tun und lassen sollte, ziemlich nützlich.
>
> Wo liegt Dein Problem?

Sorry, auch als "Nicht-C'ler" fand ich die Frage des TO erst einmal 
lesenswert! Dass sich dahinter reiner "Kinderkram" verbirgt, habe ich 
erst jetzt verstanden. Wie gesagt, die Foren sind voll von diesen 
Fragen, die sich ein "Klicker" - immerhin manchmal - stellt.

Cman schrieb:
> Wieso ist nochmal so etwas in C nicht gut?
>
> counter = counter++ % 10;
> Danke

Zur Erinnerung noch mal die Frage des TO...
Gruß Rainer

von A. S. (Gast)


Lesenswert?

Egon D. schrieb:
> Doch, natürlich -- aber wer sagt Dir, dass ich die nicht genauso
> beschissen finde?

Das ist als Anfänger völlig normal. Da kann ich doch genauso gut i=i+1; 
hinschreiben, oder inc i oder egal.

Am Ende (nach einiger Zeit Erfahrung, zählt aber nur Lesbarkeit, im 
großen Stil. Noch weiter sind die Mathematiker, mit kurzen variablen, 
globalen Konventionen und jeder Menge Sonderzeichen.

Ob du es glaubst oder nicht, Ziel ist Lesbarkeit.

von Egon D. (Gast)


Lesenswert?

Achim S. schrieb:

> Egon D. schrieb:
>> Doch, natürlich -- aber wer sagt Dir, dass ich die
>> nicht genauso beschissen finde?
>
> Das ist als Anfänger völlig normal.

Sicher -- aber Du vergisst dabei, dass ich zwar
C-Anfänger bin, aber kein Programmieranfänger.

Konstrukte, die mir zu abseitig sind, ersetze ich
durch die kanonische Form.


> Ob du es glaubst oder nicht, Ziel ist Lesbarkeit.

Ich verstehe Dein Argument nicht. Natürlich ist Lesbarkeit
(unter der Randbedingung der Korrektheit) oberstes Ziel,
aber genau deshalb verwende ich bestimmte Konstrukte
NICHT.

Ja, man DARF sich den Daumen platthauen oder in den Fuß
schießen -- aber bin ich wirklich dazu VERPFLICHTET?

von Egon D. (Gast)


Lesenswert?

Rainer V. schrieb:

> Egon D. schrieb:
>> Warum beteiligst Du Dich an einem C-Thread, wenn Dich
>> C nicht interessiert?
>>
>> Ich bin dabei, meinen Horizont von Assembler, Pascal
>> und Tcl auf C auszudehnen, und ich finde Diskussionen,
>> was man in C tun und lassen sollte, ziemlich nützlich.
>>
>> Wo liegt Dein Problem?
>
> Sorry, auch als "Nicht-C'ler" fand ich die Frage des
> TO erst einmal lesenswert! Dass sich dahinter reiner
> "Kinderkram" verbirgt, habe ich erst jetzt verstanden.

Tut mir leid... ich bin offenbar wirklich zu dumm, um zu
verstehen, was Du meinst. Dieser "Kinderkram", wie Du es
nennst, ist das, was den WESENTLICHEN Aufwand beim Lernen
von C verursacht.


> Wie gesagt, die Foren sind voll von diesen Fragen,
> die sich ein "Klicker" - immerhin manchmal - stellt.

???

von Egon D. (Gast)


Lesenswert?

Jörg W. schrieb:

> Du vergisst, dass die Eingangszeile eine Kurzform ist von
> counter = (counter = counter + 1) % 10;
> Siehst du jetzt die doppelte Zuweisung?

Ja, schon -- aber wieso ist das fehlerhaft?

Modulo bindet stärker als die (äußere) Zuweisung.
Das Plus in der Klammer bindet stärker als die
Zuweisung in der Klammer.
Also würde ich davon ausgehen, dass zuerst counter
um Eins erhöht wird, dieser erhöhte Wert dann
"counter" zugewiesen wird (was nichts ändert), dann
der Divisionsrest bestimmt wird, und schließlich das
Ergebnis wiederum counter zugewiesen wird.

Wo liegt mein Denkfehler?

von Karl K. (karl2go)


Lesenswert?

Jörg W. schrieb:
> Siehst du jetzt die doppelte Zuweisung?

Nein, das sieht man eben nicht. Das weiss man, wenn man weiss, was C mit 
++ macht. Aber die Zuweisung sieht man an der Stelle genau nicht.

Achim S. schrieb:
> lesbarer (schneller, robuster) ist If(++counter > 59) {counter = 0;}

Kommt drauf an.

Ist der Überlauf eine Zahl <> 2^n, wird auf einem µC für Modulo eine 
Softdivision aufgerufen: Das If ist schneller. Ist der Überlauf 2^n, 
wird bei Modulo einfach mit einer Bitmaske ge-AND-ed: Das If ist 
langsamer. Ist der Compiler entsprechend klever, optimiert er das If 
weg.

von Karl K. (karl2go)


Lesenswert?

CaptainA schrieb:
> Man sollte sie auf binär
> umstellen.
> 1 Tag = 32 Stunden á 64 Minuten á 64 Sekunden = 65536 Sekunden.

Funktioniert so aber nur auf Rechnern mit Halbbit-Arithmetik.

von Rainer V. (a_zip)


Lesenswert?

Egon D. schrieb:
> Tut mir leid... ich bin offenbar wirklich zu dumm, um zu
> verstehen, was Du meinst.

LOL...

von Kaj (Gast)


Angehängte Dateien:

Lesenswert?

Da sich hier ja einige ueber C++ auslassen: So sieht das leserliche C++ 
der Zukunft aus! :P

von A. S. (Gast)


Lesenswert?

Egon D. schrieb:
> Ja, schon -- aber wieso ist das fehlerhaft?
>
> Modulo bindet stärker als die (äußere) Zuweisung.
> Das Plus in der Klammer bindet stärker als die
> Zuweisung in der Klammer.
> Also würde ich davon ausgehen, dass zuerst counter
> um Eins erhöht wird, dieser erhöhte Wert dann
> "counter" zugewiesen wird (was nichts ändert), dann
> der Divisionsrest bestimmt wird, und schließlich das
> Ergebnis wiederum counter zugewiesen wird.
>
> Wo liegt mein Denkfehler?

Kein Denkfehler! Einfach nur eine Folge des "Sequence-Point"-Konzepts 
und das = halt keiner ist. Diese c-faq erklärt es relativ kompakt:

http://c-faq.com/expr/seqpoints.html

Und ja, das muss man nicht wissen, das muss man nichtmal ahnen! Und man 
muss es nicht verstehen. Es reicht, wenn man man defensiv programmiert 
und Warnungen einschaltet.

Dann kommt man die ersten Jahre auch über die Runden und fragt sich, 
warum er bei a=a++; warnt, aber nicht bei a++; oder a++;a=a; .... Und 
stellt dann meist fest, dass es eh von vornherein Blödsinn war.

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


Lesenswert?

Egon D. schrieb:
> Diese verdeckte Zuweisung ist halt eine der unzähligen Fallen in C

Naja. Sie ist ein Tribut daran, dass man sowas machen konnte:
1
   char *cp, c;
2
3
   cp = ...;
4
5
   // …
6
7
   while ((c = *cp++) != '\0') {
8
     // tu was mit "c"
9
   }

und dabei selbst mit den primitiven Compilern der damaligen Zeit auf 
einer PDP-11 im generierten Assemblercode die 
post-increment-Adressierung dieser Maschine 1:1 abbilden konnte, mithin 
in C an die Effizienz von Assembler herankam.

Das Pendant zu post-increment war auf der PDP-11 übrigens pre-decrement 
(beides zusammen brauchte man ohnehin für Stack oder das normale 
Befehlslesen), weshalb uralter C-Code eben auch wirklich nur foo++ oder 
--foo benutzt, aber praktisch nie ++foo oder foo--.  pre-increment und 
post-decrement gab es nicht als direkte Adressierungsarten, das hätte 
dann zwei Befehle gebraucht.

von A. S. (Gast)


Lesenswert?

Nachtrag: Wie es ja auch beim TO genauso klar(erst ++, dann %) und 
kompakt (Anzahl Zeichen) geht, wenn mans naiv hinschreibt
1
counter = counter++ % 10;
2
/*vs*/
3
counter++; counter %= 10;

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


Lesenswert?

Egon D. schrieb:
> Modulo bindet stärker als die (äußere) Zuweisung.

Bindung beschreibt nur, in welcher Folge die gedachte Klammerung liegt, 
aber nicht, in welcher Folge die tatsächliche Abarbeitung der Anweisung 
durch den Compiler umgesetzt werden muss.

Ansonsten würde die Sprache dem Compiler laufend bei der Optimierung im 
Weg herumstehen.

Die hier schon mehrfach genannten "sequence points" sind dann die 
Stellen, an denen der Zustand der hypothetischen Maschine, durch die die 
Anweisungen abgearbeitet sind, wieder mit der Realität übereinstimmen 
müssen.

von Egon D. (Gast)


Lesenswert?

Jörg W. schrieb:

> Egon D. schrieb:
>> Diese verdeckte Zuweisung ist halt eine der
>> unzähligen Fallen in C
>
> Naja. Sie ist ein Tribut daran, dass [...]

Ja, ich weiss.

Ich wollte auch nicht wieder die (k+1)-te Runde
dieser Diskussion einläuten, sondern damit nur sagen:

Die Schöpfer von C hatten bestimmte gute Gründe, damals
solche Konstrukte in die Sprache einzubauen.
Und wir haben heute gute Gründe, nicht unbedingt alle
Konstrukte aktiv zu verwenden, die die Sprache bietet --
einfach weil heute eben nicht damals ist. Die Entwicklung
ist weitergegangen, die Schwerpunkte und Notwendigkeiten
haben sich verschoben.

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


Lesenswert?

Egon D. schrieb:
> Und wir haben heute gute Gründe, nicht unbedingt alle Konstrukte aktiv
> zu verwenden, die die Sprache bietet

Das ist gewiss auch richtig, wenngleich man in der for-Anweisung sicher 
nur ungern drauf verzichten würde.

Man muss sich halt jedes Mal sein Werkzeug durchdenken, das man benutzt.

von S. R. (svenska)


Lesenswert?

Wilhelm M. schrieb:
> So ein kleines Template wie das obige, um bspw. einen saturierenden
> ganzzahligen, numerischen DT zu modellieren, lernt man als Studierender
> auf einer vernünftigen heutigen Hochschule im BA-Informatik im 2.
> Semester.

Das mag sein, allerdings habe ich nie Informatik (E-Technik) studiert 
und arbeite trotzdem als Softwareentwickler.

Du kannst nicht von jedem Programmierer verlangen, dass er auf dem 
aktuellen Stand der Entwicklung ist und alle Konstrukte sowohl aktiv als 
auch passiv vollständig nutzen kann. Schon garnicht für C++, welches als 
Multi-Paradigmen-Sprache extrem komplex ist.

Dr. Sommer schrieb:
>> Und die permanente Einarbeitung in immer komplexere Abstraktionsebenen
>> un  immer komplexere Sprachmittel ist kostenlos?
> Nein, aber zahlt sich aus in der eingesparten Zeit der Fehlersuche.

In erster Linie würde das bei meinem Arbeitgeber dazu führen, dass der 
Code nicht durch die Code-Review kommt. Die verwendeten - und erwarteten 
- Patterns in der verwendeten Codebasis sind festgelegt. Das gilt 
übrigens auch für Fremdcode gleicher Funktion, mit dem ich zu tun habe 
(der dann natürlich andere Patterns, andere Abstraktionsebenen und 
andere Datentypen benutzt). Es handelt sich um eine strikte Untermenge 
von C++.

Warum legt man sowas fest, statt überall die optimale Lösung zu haben?

Weil man damit mittelmäßige Programmierer, die man hat, sinnvoll 
produktiv einsetzen kann. Weil man damit viele strukturelle Fehler 
vermeiden kann. Weil man damit den Reviewer entlastet. Und so weiter.

In C++ ist es problemlos möglich, dass ein einfach aussehendes "x = x + 
1" eine zweitätige Einarbeitung benötigt, bis man wirklich verstanden 
hat, was es eigentlich tut.

> Die Klassendefinition schreibt man genau 1x und verpackt sie in eine
> Bibliothek, oder nutzt eine fertige.

Wie gesagt, das wäre bei uns nicht möglich. Und die Gründe dafür finde 
ich sowohl nachvollziehbar als auch sinnvoll.

> Aber sie lernt sich schnell wenn man die Konzepte kennt. Wie gesagt
> lohnt sich die Lern-Zeit. Oder würdest du auf die Nutzung eines CAD
> verzichten und lieber mit Stift&Papier layouten, weil das Lernen des CAD
> so lange dauert?

Das hängt davon ab, ob die erwartete Zeitersparnis durch "Lernen und 
optimiertes Verfahren benutzen" verglichen mit "ineffizientes Verfahren 
benutzen" positiv ist. Lernen ist Aufwand, den Luxus kann ich mir nicht 
immer dann gönnen, wenn es gerade sinnvoll wäre.

Mit anderen Worten: Ich automatisiere Dinge nur dann, wenn ich damit 
rechne, sie hinreichend oft benutzen zu müssen, oder sie bereits so oft 
genug benutzt habe, dass die Automatisierung trivial ist.

Achim S. schrieb:
> Vor allem führt es direkt zu Unit-Tests. Es ist nichts falsch mit
> Unit-Tests, aber insgesamt führt es zu hunderten kleinen Routinen,
> Codeschnippseln, die alle getestet sind,

Ich behaupte, dass eines der Hauptprobleme bei "das Problem in immer 
kleinere Teile schnetzeln" nicht mehr die einzelnen Teile sind, sondern 
deren Komposition. Die einem Problem inhärente Komplexität muss irgendwo 
wieder auftauchen, sonst ist das Problem nicht gelöst. Tausend kleine 
Fragmente sehe ich bei vielen Projekten nicht als Lösung, sondern als 
Problem.

Zuviel Abstraktion verschleiert den Blick aufs Wesentliche (wie in der 
Philosophie auch). Außerdem lassen sich über stark abstrahierte Objekte 
nur noch wenig konkrete Aussagen treffen, was aber nicht überall klar 
ist, wo die Abstraktion verwendet wird. Und am Ende hat man einen 
Zähler, der mal für Zahlen bis 60 entworfen wurde, dessen API aber 
wesentlich weiter reicht als dessen Implementation.

Egon D. schrieb:
> Die Schöpfer von C hatten bestimmte gute Gründe, damals
> solche Konstrukte in die Sprache einzubauen.
> Und wir haben heute gute Gründe, nicht unbedingt alle
> Konstrukte aktiv zu verwenden, die die Sprache bietet --
> einfach weil heute eben nicht damals ist.

Die vorhandenen Konstrukte prinzipiell zu verbieten, ist aber auch keine 
vernünftige Lösung. Selbst ein eher misslungene Teile (wie z.B. 
Bitfelder oder goto) lassen sich in bestimmten Fällen äußerst sinnvoll 
einsetzen - oder sind nur schwer zu vermeiden. Sprachen, in denen solche 
Konstrukte fehlen, bieten oft Alternativen.

> Die Entwicklung ist weitergegangen, die Schwerpunkte
> und Notwendigkeiten haben sich verschoben.

Dafür gibt es alternative Programmiersprachen. Die Entwicklung geht zwar 
weiter, auch in C (K&R C und C11 sind nicht die gleiche Sprache) - aber 
an den Grundfesten rütteln kann man eben nicht so einfach.

von Egon D. (Gast)


Lesenswert?

Jörg W. schrieb:

> Egon D. schrieb:
>> Und wir haben heute gute Gründe, nicht unbedingt
>> alle Konstrukte aktiv zu verwenden, die die Sprache
>> bietet
>
> Das ist gewiss auch richtig, wenngleich man in der
> for-Anweisung sicher nur ungern drauf verzichten würde.

Naja, niemand muss meine abseitigen Vorlieben teilen --
ich erwarte nur, dass ich wegen meiner andersartigen
Orientierung nicht als dumm, faul oder unprofessionell
beschimpft werde ;)

von Egon D. (Gast)


Lesenswert?

S. R. schrieb:

> Egon D. schrieb:
>> Die Schöpfer von C hatten bestimmte gute Gründe, damals
>> solche Konstrukte in die Sprache einzubauen.
>> Und wir haben heute gute Gründe, nicht unbedingt alle
>> Konstrukte aktiv zu verwenden, die die Sprache bietet --
>> einfach weil heute eben nicht damals ist.
>
> Die vorhandenen Konstrukte prinzipiell zu verbieten,
> ist aber auch keine vernünftige Lösung.

Es geht (mir) doch überhaupt nicht um "verbieten".

Es ist einfach so, dass C eine Anzahl Konstrukte kennt,
die damals aus Effizienzgründen sinnvoll waren, die aber
heute die Lesbarkeit der Programme nicht unbedingt
verbessern.
Niemand sagt, dass man die Konstrukte heute nicht mehr
einsetzen darf -- davon ist keine Rede. Wer mir aber
ausgerechnet diese Konstrukte als DIE großen Errungen-
schaften von C verkaufen will, offenbart ein in meinen
Augen sehr verdrehtes Verständnis von Softwareentwicklung.

Hochsprachen sind NUR für den Menschen da, der Computer
ist auch mit Binärzahlen zufrieden.


>> Die Entwicklung ist weitergegangen, die Schwerpunkte
>> und Notwendigkeiten haben sich verschoben.
>
> Dafür gibt es alternative Programmiersprachen.

Naja, auch diese Diskussion ist für mich schon durch:
Außer C (und Forth) wüsste ich keine Sprache, die
mit weitgehend identischer Syntax auf praktisch jedem
Prozessor verfügbar ist. (Assembler zählt nicht, da
ist nur der NAME identisch, nicht die Syntax.)

Insofern: Nein, es gibt leider nicht immer alternative
Programmiersprachen.

von Egon D. (Gast)


Lesenswert?

Achim S. schrieb:

>> Wo liegt mein Denkfehler?
>
> Kein Denkfehler! Einfach nur eine Folge des
> "Sequence-Point"-Konzepts und das = halt keiner ist.

Hmm.
Ich habe offenbar den subtilen Unterschied zwischen
"undefined behavior" und "unspecified behavior" nur
mangelhaft verstanden.

Ich bin davon ausgegangen, dass ein Freiheitsgrad in
der Reihenfolge der Auswertung besteht, der, abhängig
vom konkreten Compiler, zu unterschiedlichen Resultaten
führen kann (="unspecified behavior"?!).

Richtig scheint aber zu sein, dass der Compiler das
Konstrukt schlicht und ergreifend nicht übersetzen
muss (="undefined behavior"?!).


> Und ja, das muss man nicht wissen, das muss man nichtmal
> ahnen! Und man muss es nicht verstehen.

Meine Güte... worauf habe ich mich eingelassen...

von Dr. Sommer (Gast)


Lesenswert?

Egon D. schrieb:
> Gottseidank habe ich den Luxus, in 90% aller Fälle einfach
> foreach ding $dingliste {
> ...
> }
>  schreiben zu können,

Tja, es gibt da eine Sprache die das kann... Die nennt sich C++.

von Wilhelm M. (wimalopaan)


Lesenswert?

Dr. Sommer schrieb:
> Egon D. schrieb:
>> Gottseidank habe ich den Luxus, in 90% aller Fälle einfach
>> foreach ding $dingliste {
>> ...
>> }
>>  schreiben zu können,
>
> Tja, es gibt da eine Sprache die das kann... Die nennt sich C++.

Oh, in einem C-Thread C++ erwähnen ... teuflisch. Tcl, etc. ist erlaubt, 
aber doch kein C++.

Die Sprache C++ ist doch soo komplex, man muss(!) auch immer die ganze 
Sprache mit allen (alten wie neuen) Features auf einmal(!) lernen, 
deswegen ist das unbeherrschbar. Man muss(!) auch OOP benutzen, und 
deswegen ist das nicht für µC einsetzbar. Und man muss(!) auch TMP 
benutzen, dieses abstrakte Informatikerzeugs. Und dann noch die 
Bibliothek dazu, von einem Mathematiker(!) ersonnen: ein Graus. Ja, und 
Linus findet sie auch doof ... das verpflichtet.

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

Egon D. schrieb:
> Richtig scheint aber zu sein, dass der Compiler das Konstrukt schlicht
> und ergreifend nicht übersetzen muss (="undefined behavior"?!).

Noch schlimmer: mit einem UB braucht er auch alle Zeilen vor- und 
nachher nicht mehr richtig zu übersetzen. Er kann sich dabei quasi 
intern beliebig verschlucken und woanders Müll machen. Und dazu 
braucht's keine Schachtelkonstrukte, es reicht ein int-überlauf mit i++;

von Cman (Gast)


Lesenswert?

Wow, ich denke, ich muss mir da mal etwas länger Zeit nehmen.
Sind ja ein paar mehr antworten :)

von HyperMario (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Oh, in einem C-Thread C++ erwähnen ... teuflisch. Tcl, etc. ist erlaubt,
> aber doch kein C++.

Du kannst natürlich machen was du willst, aber wer außer dir meint das 
Tlc
"erlaubt" sei? Klingt nach ner faden Ausrede für sinnloses Gelaber über 
eine andere Sprache (die übrigens für meine Hardware gar nicht existiert 
und das geschwurbel da sinnlos ist).

In der Richtung war der beste Beitrag hier übrigens der mit dem Känguru 
und den Daumen, versteht aber nicht jeder.

von Wilhelm M. (wimalopaan)


Lesenswert?

HyperMario schrieb:
> Wilhelm M. schrieb:
>> Oh, in einem C-Thread C++ erwähnen ... teuflisch. Tcl, etc. ist erlaubt,
>> aber doch kein C++.
>
> Du kannst natürlich machen was du willst, aber wer außer dir meint das
> Tlc
> "erlaubt" sei? Klingt nach ner faden Ausrede für sinnloses Gelaber über
> eine andere Sprache (die übrigens für meine Hardware gar nicht existiert
> und das geschwurbel da sinnlos ist).

Ich glaube, Du hast jetzt grad gar nichts verstanden ;-)

von S. R. (svenska)


Lesenswert?

Egon D. schrieb:
> Wer mir aber ausgerechnet diese Konstrukte als DIE
> großen Errungenschaften von C verkaufen will,
> offenbart ein in meinen Augen sehr verdrehtes
> Verständnis von Softwareentwicklung.

Jaein. Diese Konstrukte waren tatsächlich die großen Errungenschaften 
von C, in ihrer Zeit. Heute sind sie das nicht mehr. Genauso wie das 
Auto, der Taschenrechner, überhaupt Computer große Errungenschaften 
ihrer Zeit waren.

Sie sind es alle heute nicht mehr.
Deswegen sind sie trotzdem nicht obsolet.

> Hochsprachen sind NUR für den Menschen da, der Computer
> ist auch mit Binärzahlen zufrieden.

Es gibt Programmiersprachen, die möchten den Menschen maximal 
bevorzugen. Mir ist aber ein ausgewogener Kompromiss wichtiger: Ich 
möchte eine Sprache haben, die für mich benutzbar ist, aber trotzdem 
noch die zugrundeliegende Maschine durchscheinen lässt.

Ich bin kein Webentwickler.

> Naja, auch diese Diskussion ist für mich schon durch:
> Außer C (und Forth) wüsste ich keine Sprache, die mit weitgehend
> identischer Syntax auf praktisch jedem Prozessor verfügbar ist.

Da gäbe es zum Beispiel C++. Außerdem kann man einige höhere Sprachen in 
C-Code übersetzen lassen oder als C-Bibliothek einbinden.

Egon D. schrieb:
> Ich habe offenbar den subtilen Unterschied zwischen
> "undefined behavior" und "unspecified behavior" nur
> mangelhaft verstanden.

Wenn in deinem Programm irgendwo "undefined behaviour" auftritt, dann 
war das Programm schon vor dem Aufruf des Compilers fehlerhaft. Dem 
Compiler steht es frei, das Programm fehlerfrei, fehlerhaft oder auch 
garnicht zu kompilieren, und er muss dir auch nicht sagen, was davon er 
gemacht hat.

Wenn in deinem Programm irgendwo "implementation-defined" behaviour 
auftritt, dann durfte der Compilerhersteller entscheiden, was er tut 
(und musste das auch dokumentieren). Das Verhalten ist damit vollständig 
definiert (für diesen Compiler, in dieser Version, auf dieser 
Plattform).

Ich habe in dem Zusammenhang noch nicht von "unspecified behaviour" 
gehört, das ist meinem Verständnis nach schlicht dasselbe wie "undefined 
behaviour".

> Ich bin davon ausgegangen, dass ein Freiheitsgrad in
> der Reihenfolge der Auswertung besteht, der, abhängig
> vom konkreten Compiler, zu unterschiedlichen Resultaten
> führen kann (="unspecified behavior"?!).

Nein, die Auswertungsreihenfolge von "du schreibst eine Variable 
mehrfach ohne Sequenzpunkt" ist schlicht undefiniert und damit auch das 
Verhalten des Programms. Vor dem Compileraufruf, deswegen muss der 
Compiler das Programm auch nicht übersetzen.

Ein Funktionsaufruf func(x++, x++, x++) ist ebenfalls undefiniert, aus 
dem gleichen Grund.

Die Auswertung von if(x==0 && y==1 && z==2) hingegen muss von links nach 
rechts erfolgen (und abkürzen).

von Carl D. (jcw2)


Lesenswert?

Wilhelm M. schrieb:
> HyperMario schrieb:
>> Wilhelm M. schrieb:
>>> Oh, in einem C-Thread C++ erwähnen ... teuflisch. Tcl, etc. ist erlaubt,
>>> aber doch kein C++.
>>
>> Du kannst natürlich machen was du willst, aber wer außer dir meint das
>> Tlc
>> "erlaubt" sei? Klingt nach ner faden Ausrede für sinnloses Gelaber über
>> eine andere Sprache (die übrigens für meine Hardware gar nicht existiert
>> und das geschwurbel da sinnlos ist).
>
> Ich glaube, Du hast jetzt grad gar nichts verstanden ;-)

@Wilhem:
Ich glaube ich hatte es schon mal erwähnt:
Nutz die Zeit für Besseres. Schau dir CppCon Vorträge an, 2018 gibt's 
wieder einen guten von Dan Saks, da hat man was von, anders als bei den 
Diskussionen hier.

von Wilhelm M. (wimalopaan)


Lesenswert?

Carl D. schrieb:
> Wilhelm M. schrieb:
>> HyperMario schrieb:
>>> Wilhelm M. schrieb:
>>>> Oh, in einem C-Thread C++ erwähnen ... teuflisch. Tcl, etc. ist erlaubt,
>>>> aber doch kein C++.
>>>
>>> Du kannst natürlich machen was du willst, aber wer außer dir meint das
>>> Tlc
>>> "erlaubt" sei? Klingt nach ner faden Ausrede für sinnloses Gelaber über
>>> eine andere Sprache (die übrigens für meine Hardware gar nicht existiert
>>> und das geschwurbel da sinnlos ist).
>>
>> Ich glaube, Du hast jetzt grad gar nichts verstanden ;-)
>
> @Wilhem:
> Ich glaube ich hatte es schon mal erwähnt:
> Nutz die Zeit für Besseres. Schau dir CppCon Vorträge an, 2018 gibt's
> wieder einen guten von Dan Saks, da hat man was von, anders als bei den
> Diskussionen hier.

Ja klar, aber ist doch wieder lustig hier ;.)
Habe schon fast alle gesehen: der von Andrew Sutton und Ben Deane 
gehören m.E. zu den besten.

von Rolf M. (rmagnus)


Lesenswert?

S. R. schrieb:
> Ich habe in dem Zusammenhang noch nicht von "unspecified behaviour"
> gehört, das ist meinem Verständnis nach schlicht dasselbe wie "undefined
> behaviour".

Nein. Es ist wie implepementation-defined behavior, nur dass nicht 
dokumentiert werden muss, wofür sich der Compiler-Hersteller entschieden 
hat.

von Rainer V. (a_zip)


Lesenswert?

Ja, die ewigen Grabenkriege...nachdem seinerzeit unser Chefentwickler 
sein Projekt - komplett in Lab-View - abgeschlossen hatte und seinen Hut 
nahm, wurde beschlossen, den Code zwecks besserer Wartung (Chefidee..) 
in C# (oder so) zu konvertieren. Nachdem das zu ernsten Problemen 
führte, wurde C++ angesetzt! Dieses (interne!) Projekt gibt seitdem 
(gefühlte 20 Jahre) einer Vollzeitkraft und diversen Hilfskräften Wasser 
und Brot! Einzig der unglaubliche Erfolg des Produkts hat dies 
ermöglicht...es erinnert mich fast an Stenkelfeld, die 
Weihnachtsbeleuchtung...
Schönen Abend noch, Rainer

Cman schrieb:
> Wieso ist nochmal so etwas in C nicht gut?
>
> counter = counter++ % 10;

Ehrlich, keine Ahnung :-)

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.