Forum: PC-Programmierung Einheitliche Regel für in C erstellte Variablen, Typen etc


von KArl Fred M. (Gast)


Lesenswert?

Wie richtet ihr euren Code ein?
Also wie schreibt ihr Variablen und wie Konstanten?
Typen, Funktionen etc.
Also  gibt es hier eine einheitliche Empfehlung?
Also Variablen mit einem v_ voran?
oder Variablen klein Konstanten die ersten beiden Zeichen groß oder so?

von DPA (Gast)


Lesenswert?

Ich nehme alles gross für enum werte und defines, ansonsten überal 
klein. Überall snake case. Und alles was global ist bekommt einen 
namespace. util_fancy_function, util_other_thing, etc. Wobei meistens 
nehme ich da den Projektnamen als Prefix.

von KArl Fred M. (Gast)


Lesenswert?

und wie unterscheidet ihr globale von lokalen Variablen z.B.

von N. M. (mani)


Lesenswert?

Schau dich doch einfach Mal im Internet um bei den ganzen Coding Style 
Guides/Rules. Das ist einfach zu viel um das alles hier auf zu zählen.

Ein "kleines" Beispiel:
https://google.github.io/styleguide/cppguide.html

Ich denke man muss für sich bzw. im Team herausfinden was man wie 
umsetzen will bzw. am besten findet. Den "richtigen" Weg wird es nicht 
geben.
Frag bei Linus nach der richtigen Art zu kommentieren 😂

von KArl Fred M. (Gast)


Lesenswert?

Namespace bei C? Gibt es das da auch?

von DerEinzigeBernd (Gast)


Lesenswert?

KArl Fred M. schrieb:
> Gibt es das da auch?

Nein. "mani" hat einen cpp-Guide verlinkt, warum auch immer.

Den "richtigen" Coding Style zu finden ist wie die "richtige" Religion 
zu finden, es gibt viele verschiedene und deren Anhänger mögen jeweils 
die anderen nicht.

Das fängt schon bei Einrückungen an, oder dem Gebrauch von Tabulatoren 
und deren Abständen ...

Und ob man lange_namen_mit_underscores mag oder CamelCase, oder ob man 
"ungarische Notation" mit Typ-Präfixen mag ... es sind schon Ehen aus 
nichtigeren Anlässen geschieden worden.

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


Lesenswert?

KArl Fred M. schrieb:
> und wie unterscheidet ihr globale von lokalen Variablen

Indem die Komplexität deines Codes klein genug ist, als dass du das 
überschauen kannst. Eine lokale Variable erkennst du also daran, dass du 
deren Definition bereits auf dem Bildschirm sehen kannst. Außerdem 
minimiert man den Gebrauch von globalen Variablen sowieso so weit wie 
möglich.

Sauber strukturierter Code ist wichtiger als irgendwelche schrägen 
Namenskonventionen, die nur zu Gehirnverrenkungen führen. "Ungarische" 
Notation ist das beste Beispiel dafür. Als ich das erste Mal eine 
Variable gesehen habe, die mit "lp" anfing, habe ich mich gefragt, was 
zum Geier an der Stelle denn der line printer ins Spiel kommt.

von N. M. (mani)


Lesenswert?

DerEinzigeBernd schrieb:
> "mani" hat einen cpp-Guide verlinkt, warum auch immer.

Weil die Obermenge von CPP auch auf C angewendet werden kann. Die 
Transferleistung die benötigten Dinge heraus zu filtern vorausgesetzt.

von J. S. (jojos)


Lesenswert?

Mit einer guten IDE sind Namen Schall und Rauch.
Cursor auf Variable/Funktion: Tooltip zeigt Typ an. Ctrl+Klick: Editor 
öffnet die Deklaration. Zurück Taste an der Maus: Editor springt wieder 
zurück wo er hergekommen ist. usw.
Gut, wer sich notepad oder nano für Quellcodes antut, der kennt man das 
natürlich nicht.

Bei Projekten mit vielen Sourcecode Libs wird man kaum einen 
einheitlichen Stil finden. Oder wenn man an einem Projekt als 
Teammitglied arbeitet, dann muss man sich an die Regeln des Projektes 
halten.

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


Lesenswert?

KArl Fred M. schrieb:
> Wie richtet ihr euren Code ein?

Wie ein Lager.

Wenn ich nur 3 schrauben brauche und noch nicht klar ist, welche, heißen 
die Fächer 1, 2 und 3, analog zu vielleicht i, j und n.

Wenn ich 30 zöllige und 20 metrische habe, sind die Fächer vielleicht 
mit M5x20 beschriftet. Wenn alle metrisch sind, entfällt das M.

Konsens ist eigentlich nur, dass nur #defines komplett groß geschrieben 
werden. Für alles andere werden die Konstrukte umso komplexer, je mehr 
Token es gibt.

Ob Du schraube_m8_20 schreibst, schraube.M8.L20, S8x20 oder 
SchraubeM8x20 ist die ersten Jahre egal.

Im großen Lager verlierst Du mit S4711 den Überblick, im kleinen wirst 
Du mit achraube_metrisch_steigung_normal_nach_norm_durchmesser8_laenge20 
wahnsinnig.

von Wühlhase (Gast)


Lesenswert?

Ich benutze die Regeln, die sonst für Java empfohlen sind:
-Funktionen camelCase, klein beginnend, der Name beginnt meist mit einem 
Verb.

-Variablen klein, camelCase, auf keinen Fall solchen Unsinn wie 
ungarische Notation.

-Konstanten durchgängig GROSS.

...usw...

von Yalu X. (yalu) (Moderator)


Lesenswert?

KArl Fred M. schrieb:
> Also wie schreibt ihr Variablen und wie Konstanten?
> Typen, Funktionen etc.

Ganz einfach:

Je größer der Scope, desto aussagekräftiger der Name.

Je kleiner der Scope, desto kürzer der Name.

von Noch ein Kommentar (Gast)


Lesenswert?

Normalerweise benutzt man ja irgend ein Framework. Oder schlachtet ein 
halbwegs passendes Opensource-Programm aus.

Wenn 3/4 der Klassen aus Qt oder ähnlichem stammen, übernimmt man halt 
deren Konventionen. Und wenn man mit kleinen Erweiterungen eines 
bestehenden Programmes anfängt, nimmt man deren Schreibweise.

Wenn du das beruflich machst, müsst du eh bei jedem Auftrag andere 
Konventionen übernehmen.

(Und dann gibt es noch ein Problem - du fängst mit englischen Namen an, 
aber kennst die Übersetzungen der Fachbegriffe nicht. Bekommst Namen, 
die aus englischen und deutschen Teilen bestehen).

von cppbert (Gast)


Lesenswert?

KArl Fred M. schrieb:
> und wie unterscheidet ihr globale von lokalen Variablen z.B.

auch wenn das einige schmerzt nutze ich gerne solche Prefixe wie

g_ Global
s_ Static
p_ Parameter
m_ Member
lokale Variable ohne Prefix

g_, s_ und p_ sind so fiese das die sofort in jedem Code auffallen

aber keine Type-information mit rein wie bei der Ungarische Notation

von PittyJ (Gast)


Lesenswert?

cppbert schrieb:
>
> auch wenn das einige schmerzt nutze ich gerne solche Prefixe wie
>
> g_ Global
> s_ Static
> p_ Parameter
> m_ Member
> lokale Variable ohne Prefix
>
> g_, s_ und p_ sind so fiese das die sofort in jedem Code auffallen
>
> aber keine Type-information mit rein wie bei der Ungarische Notation

Ich nehme immer noch die ungarische Notation. Gerade bei Sourcecode, den 
man lange nicht bearbeitet hat, da hilft das ungemein.

f_Counter = 1;

Da weiss ich sofort, der Counter ist vom Type Float. Da brauch ich nicht 
mehr oben bei der Deklaration, oder bei Klassen im .H-File nachschauen.

und wenn dann da steht

i_Index = f_Counter ;

Dann weiss ich, da werden Ints und Floats vermixt, das kann Probleme 
geben.

Das hilft mir seit 20 Jahren.

von Yalu X. (yalu) (Moderator)


Lesenswert?

PittyJ schrieb:
> f_Counter = 1;

Dieser Name ist für mich schon ein Widerspruch in sich :)

von KArl Fred M. (Gast)


Lesenswert?

@PittyJ
Ja, mir gefällt die Ungarische Notation bislang auch am besten

von Yalu X. (yalu) (Moderator)


Lesenswert?

KArl Fred M. schrieb:
> Ja, mir gefällt die Ungarische Notation bislang auch am besten

Apps Hungarian oder Systems Hungarian?

Zur Erläuterung der Unterschiede:

  https://en.wikipedia.org/wiki/Hungarian_notation

von Wühlhase (Gast)


Lesenswert?

PittyJ schrieb:
> Ich nehme immer noch die ungarische Notation. Gerade bei Sourcecode, den
> man lange nicht bearbeitet hat, da hilft das ungemein.

Da setze ich den Cursor in den Namen, und links gibt es ein Feld das 
einem anzeigt von welchem Typ die Variable ist. Wenn man es überhaupt 
mal wissen muß, diese Fälle sind bei mir eher selten.

Ach ja, Strg+Klick auf die Variable springt zu deren Deklaration.

von DerEinzigeBernd (Gast)


Lesenswert?

Wühlhase schrieb:
> Da setze ich den Cursor in den Namen

Es gibt ja Leute, die beim Lesen von Text immer mit dem Zeigefinger auf 
das aktuelle Wort zeigen müssen.

Ich kann meine Augen erheblich schneller bewegen als den Mauszeiger, und 
ich fände es lästig, ständig mit der Maus wedeln zu müssen, um dann auch 
noch woanders hinsehen zu müssen, um (natürlich leicht verzögert) 
Zusatzinformationen angezeigt zu bekommen.

Lesefluss ist etwas anderes.

von Udo K. (udok)


Lesenswert?

Hier noch ein guter Link zum Thema - falls noch nicht alle Klarheiten 
beseitigt sind :-)

https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/

von A. S. (Gast)


Lesenswert?

DerEinzigeBernd schrieb:
> Lesefluss ist etwas anderes.

Das ist richtig. Nur ist es m.E. äußerst selten, dass der Typ einer 
Variablen strittig ist. Eher, ob sie auf 8 oder 16 Bit beschränkt ist 
oder signed/unsigned. Dann bin ich aber ganz schnell bei ellenlangen 
präfixen.

von KArl Fred M. (Gast)


Lesenswert?

Ist man das?
I_32Test
W_16Test2
etc

Aber genau darum geht es mir, dafür schöne Beispiel zu finden, wie das 
einige umsetzen. Oftmals entdeckt man dann ja tolle Lösungen

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


Lesenswert?

KArl Fred M. schrieb:
> Ist man das?
> I_32Test
> W_16Test2
> etc

Wie schriebt ihr so schön?

Guter Lesefluss ist jedenfalls was anderes als so ein Gestotter. ;-)

> schöne Beispiel zu finden, wie das einige umsetzen.

Siehe Yalu: je kleiner der Scope, desto kürzer die Namen. Unmittelbare 
Schleifen dann auch gern mit i, j und k.  TotalNumberOfFoo (oder 
total_number_of_foo) dann eher für globulweite Variablen.

: Bearbeitet durch Moderator
von KArl Fred M. (Gast)


Lesenswert?

Jörg W. schrieb:
> Wie schriebt ihr so schön?
>
> Guter Lesefluss ist jedenfalls was anderes als so ein Gestotter. ;-)

ICh denke da liegst Du falsch, also damit, mein Beispiel jetzt als 
Beispiel zu nehmen.
Mein Beispiel ist sicher nicht ein schönes, daher habe ich diesen Thread 
ja überhaut erst gestartet....

Aber über alles andere lässt sich ja diskutieren:-)

von A. S. (Gast)


Lesenswert?

KArl Fred M. schrieb:
> mein Beispiel jetzt als Beispiel zu nehmen.

Wie mehrfach geschrieben hängt es vom Kontext ab. "Akademische" 
Beispiele mit 10 oder 20 Variablen sind praktisch wertlos.

Solange Dein Programm aus wenigen 1000 Zeilen und 100 Token besteht, ist 
jedes System OK.

Es ist heute auch völlig OK, zu refakturieren (hier: umzubenennen). Mit 
der Lager-Metapher: Der erste Sortimentskasten wird irgendwie 
beschriftet. Sobald 10 weitere da sind, ist vielleicht absehbar, wohin 
die Reise geht und man versucht, möglichst lesbare, kurze (nicht 
kryptische) verständliche Namen mit intuitiver Systematik zu finden. So 
dass bei einer neuen Variable praktisch schon vorher klar ist, wie sie 
heißen wird.

Sobald sich das Lager dann nochmal verzehnfacht, kann es sein dass alle 
Schrauben-Fächer umbenannt werden, damit es übersichtlicher wird.

von Noch ein Kommentar (Gast)


Lesenswert?

> ... ist vielleicht absehbar, wohin die Reise geht

Stimmt. Volltreffer!

Von Brooks "Mythical Man-Month" bis Raymonds "Cathedral and the Bazaar" 
- ein Punkt hat sich niemals geändert und wird sich nicht ändern: Deinen 
ersten Versuch wirfst du sowieso weg.

Du merkst, das ist doch nicht so einfach und für den zweiten Versuch 
nimmst du dann Tensorflow, OpenCV und Python. Arbeitest ein Tutorial 
durch und übernimmst auch die Konventionen für die Variablennamen.

von cppbert (Gast)


Lesenswert?

PittyJ schrieb:
> Ich nehme immer noch die ungarische Notation. Gerade bei Sourcecode, den
> man lange nicht bearbeitet hat, da hilft das ungemein.
>
> f_Counter = 1;
>
> Da weiss ich sofort, der Counter ist vom Type Float. Da brauch ich nicht
> mehr oben bei der Deklaration, oder bei Klassen im .H-File nachschauen.

bringt bei Structs oder Klassen relativ schnell gar keinen Mehrwert mehr
oder erschwert nur Refaktoring - primär ist der Scope der Variable 
wichtig um zu erkennen welchen Einfluss diese haben kann

von Mark B. (markbrandis)


Lesenswert?

PittyJ schrieb:
> Ich nehme immer noch die ungarische Notation. Gerade bei Sourcecode, den
> man lange nicht bearbeitet hat, da hilft das ungemein.
>
> f_Counter = 1;
>
> Da weiss ich sofort, der Counter ist vom Type Float.

Also wenn schon, dann so:

f_Counter = 1.0;

...und dann kann man das f_ auch wiederum weglassen, weil man durch die 
Zuweisung sieht dass es hier offensichtlich nicht um einen Integer geht. 
:-)

von Mark B. (markbrandis)


Lesenswert?

Yalu X. schrieb:
> PittyJ schrieb:
>> f_Counter = 1;
>
> Dieser Name ist für mich schon ein Widerspruch in sich :)

Vielleicht will er Tafeln Schokolade zählen, und es sind immer schon ein 
paar angefuttert? ;-)

von J. S. (jojos)


Lesenswert?

Mark B. schrieb:
> f_Counter = 1.0;

nee, da holt man sich double um sie zum float zu machen. Hier macht es 
vielleicht nichts aus und der Compiler macht gleich eine float Konstante 
raus, aber das fehlende 'f' kann einiges an Codezuwachs und CPU Last 
verursachen.

f_counter = 1.0f;

Aber auch nur float wenn der auch halbe Kekse zählen soll.

von Euro (Gast)


Lesenswert?

Wühlhase schrieb:
> Ich benutze die Regeln, die sonst für Java empfohlen sind:
> -Funktionen camelCase, klein beginnend, der Name beginnt meist mit einem
> Verb.
>
> -Variablen klein, camelCase,
Da stellt sich mir immer die Frage: Wieso mit nem Kleinbuchstaben 
beginnend?
Es sind doch Funktions- oder Variablen-"namen". Namen beginnen auch in 
Englisch üblicherweise groß?!
Und bezogen auf das namensgebende Kamelbild: verdammt, wer fängt denn 
beim Kamelpopo an und geht über die Höcker zum Kopp? Ich meine, so'n 
Kamel hat doch ne biologisch geplante Vorzugsrichtung und wir schreiben 
auch nicht die Worte von hinten nach vorne.

Versteh ich wieder alles nicht.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Euro schrieb:
> Und bezogen auf das namensgebende Kamelbild: verdammt, wer fängt denn
> beim Kamelpopo an und geht über die Höcker zum Kopp? Ich meine, so'n
> Kamel hat doch ne biologisch geplante Vorzugsrichtung und wir schreiben
> auch nicht die Worte von hinten nach vorne.

Viele Kamele gehören Beduinen, und die schreiben von rechts nach links.
Wenn du in der Sprache بلق programmierst, siehst du alles richtig herum:

  https://en.wikipedia.org/wiki/Qalb_(programming_language)

:)

Edit: Mist, die Beduinen haben wohl gar keine Groß-/Kleinschrift,
deswegen kommen sie gar nicht in den Genuss von esaClemaC :-(

: Bearbeitet durch Moderator
von loeti2 (Gast)


Lesenswert?

Ich finde man sollte Programme in einer richtigen Textverarbeitung 
schreiben.
Dann kann man lokale Variablen fett schreiben, außer (bei C++) 
Membervariablen die schreibt man kursiv.
Globale Variablen werden unterstrichen.

Kommentare werden in Blau geschrieben, und statt
1
#if 0
2
...
3
#endif
wird zur Zeit nicht benötigter Code als durchgestrichen formatiert.

:))

von Yalu X. (yalu) (Moderator)


Lesenswert?

loeti2 schrieb:
> Ich finde man sollte Programme in einer richtigen Textverarbeitung
> schreiben.
> Dann kann man lokale Variablen fett schreiben, außer (bei C++)
> Membervariablen die schreibt man kursiv.
> Globale Variablen werden unterstrichen.

Das geht in ähnlicher Form sogar ohne Textverarbeitung.

Durch den Standard vorgegebene Schlüsselwörter und Symbole werden
passenderweise in Standardschrift geschrieben, alle selbstdefinierten
Klassen, Funktionen, Argumente sowie globale, lokale und Membervariablen
bekommen jeweils ihre eigene Schriftart:
1
#include <iostream>
2
3
class 𝕶𝖑𝖆𝖘𝖘𝖊 {
4
  public:
5
    𝕶𝖑𝖆𝖘𝖘𝖊(int 𝐴𝑟𝑔𝑢𝑚𝑒𝑛𝑡): ℳℯ𝓂𝒷ℯ𝓇𝒱𝒶𝓇𝒾𝒶𝒷𝓁ℯ{𝐴𝑟𝑔𝑢𝑚𝑒𝑛𝑡} {}
6
7
    int 𝔽𝕦𝕟𝕜𝕥𝕚𝕠𝕟(int 𝐴𝑟𝑔𝑢𝑚𝑒𝑛𝑡) {
8
      int 𝗹𝗼𝗸𝗮𝗹𝗲𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲 = 2 * 𝐴𝑟𝑔𝑢𝑚𝑒𝑛𝑡;
9
      𝗹𝗼𝗸𝗮𝗹𝗲𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲 += ℳℯ𝓂𝒷ℯ𝓇𝒱𝒶𝓇𝒾𝒶𝒷𝓁ℯ;
10
      return 𝗹𝗼𝗸𝗮𝗹𝗲𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲;
11
    }
12
  private:
13
    int ℳℯ𝓂𝒷ℯ𝓇𝒱𝒶𝓇𝒾𝒶𝒷𝓁ℯ;
14
};
15
16
𝕶𝖑𝖆𝖘𝖘𝖊 𝓰𝓵𝓸𝓫𝓪𝓵𝓮𝓼𝓞𝓫𝓳𝓮𝓴𝓽{2};
17
int 𝓰𝓵𝓸𝓫𝓪𝓵𝓮𝓥𝓪𝓻𝓲𝓪𝓫𝓵𝓮;
18
19
int main() {
20
  𝓰𝓵𝓸𝓫𝓪𝓵𝓮𝓥𝓪𝓻𝓲𝓪𝓫𝓵𝓮 = 𝓰𝓵𝓸𝓫𝓪𝓵𝓮𝓼𝓞𝓫𝓳𝓮𝓴𝓽.𝔽𝕦𝕟𝕜𝕥𝕚𝕠𝕟(5);
21
  std::cout << 𝓰𝓵𝓸𝓫𝓪𝓵𝓮𝓥𝓪𝓻𝓲𝓪𝓫𝓵𝓮 << '\n';
22
  return 0;
23
}

Ausgabe:
1
12

(getestet mit g++ und clang++)

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


Lesenswert?

Yalu X. schrieb:
> Das geht in ähnlicher Form sogar ohne Textverarbeitung.

ROTFL :-))

von Udo K. (udok)


Lesenswert?

Oder etwas sinnvoller:
1
// 
2
// C++ mit Unicode Symbols
3
//
4
5
const double π = 3.14159265358979323846;
6
7
8
double foo(double A, double B, double uₙ, double uₙ₋₁, double Aₜₒₜ)
9
{
10
    double uₙ₊₁ᵖ = A*uₙ + B*uₙ₋₁;
11
    double uₙ₊₁ᶜ = π * Aₜₒₜ;
12
    double uₙ₊₁ = uₙ₊₁ᵖ + uₙ₊₁ᶜ;
13
14
    return uₙ₊₁;
15
}

von Yalu X. (yalu) (Moderator)


Lesenswert?

Udo K. schrieb:
> double uₙ₋₁

Mit welchem Compiler geht das? Bei mir regen sich GCC und Clang beide
darüber auf, dass '₋' und '₁' in Identifiern nicht erlaubt seien.

Ganz cool wäre es natürlich, wenn uₙ₋₁ in einem Ausdruck vom Compiler
als u[n-1] interpretiert würde :)

von Udo K. (udok)


Lesenswert?

Yalu X. schrieb:
>> double uₙ₋₁
>
> Mit welchem Compiler geht das? Bei mir regen sich GCC und Clang beide
> darüber auf, dass '₋' und '₁' in Identifiern nicht erlaubt seien.
>
> Ganz cool wäre es natürlich, wenn uₙ₋₁ in einem Ausdruck vom Compiler
> als u[n-1] interpretiert würde :)

Also für mathelastigen Code ist das schon eine Überlegung wert.

Ich habe das mit dem Visual Studio cl.exe compiliert.
Der clang-cl geht auch unter Win10.

Im neuesten C++ Standard haben sie aber einen Rückzieher gemacht,
und lassen nicht mehr alle gültigen Unicode Identifier Character als 
Identifier zu... keine Ahnung was für Wappler dort 2022 solche 
Entscheidungen treffen...
1
bool 👷 = true;     //  Construction Worker
2
bool 👷♀ = false;   // Woman Construction Worker
3
4
int ✋ = 0;
5
int 👊 = 0;
6
7
int ✈ = 0;
8
int 🚀 = 0;
9
10
int ☹ = 0;
11
int 😀 = 0;
12
13
int smile(int 💀)
14
{
15
    return !💀;
16
}
17
18
double bar(double φ, double uₙ₊₁);
19
{
20
    return 2 * π * sin(φ * uₙ₊₁);
21
}

: Bearbeitet durch User
von J. S. (jojos)


Lesenswert?

cool, der gcc 11.3 hat das auch akzeptiert:
1
    int 💡=1;
2
    DigitalOut light(PA_0);
3
    light = 💡;

für Licht an/aus wären noch bessere Symbole sinnvoll. Nur 
Fehlermedlungen vom Compiler sehen kryptisch aus weil da die Symbole 
nicht so angezeigt werden.
Aber gut finde ich das auch nicht.

von Yalu X. (yalu) (Moderator)


Lesenswert?

J. S. schrieb:
> int 💡=1;


Das lässt den Begriff der "grafischen Programmierung" in einem ganz
neuen Licht erscheinen ;-)

von Jan K. (jan_k)


Lesenswert?

Gibt Sprachen, wie z.B Julia, die unicode nativ unterstützen und per 
LaTeX Befehl eingegeben werden können. Ist ziemlich cool
 statt
1
theta=2*PI
 zu schreiben. Erhöht die Lesbarkeit bei Mathe Krams massiv.

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

Jan K. schrieb:
>
1
theta=2*PI

Warum sollte man eine Konstante mit Kleinbuchstaben schreiben? 🧐

von Wühlhase (Gast)


Lesenswert?

Euro schrieb:
> Wühlhase schrieb:
>> Ich benutze die Regeln, die sonst für Java empfohlen sind:
>> -Funktionen camelCase, klein beginnend, der Name beginnt meist mit einem
>> Verb.
>>
>> -Variablen klein, camelCase,
> Da stellt sich mir immer die Frage: Wieso mit nem Kleinbuchstaben
> beginnend?
> Es sind doch Funktions- oder Variablen-"namen". Namen beginnen auch in
> Englisch üblicherweise groß?!
> Und bezogen auf das namensgebende Kamelbild: verdammt, wer fängt denn
> beim Kamelpopo an und geht über die Höcker zum Kopp? Ich meine, so'n
> Kamel hat doch ne biologisch geplante Vorzugsrichtung und wir schreiben
> auch nicht die Worte von hinten nach vorne.

Das ist in C zwar weniger wichtig, aber in Java hast du damit eine gute 
Trennung zwischen Klasse und Instanzvariable. Klassen sind normalerweise 
ja Nomen, die werden in der weltweit häufig genutzen Lingua Franca 
Deutsch groß geschrieben. ;)

Eine einheitlich sinnvolle Schreibweise für Variablen ist schwierig. 
Booleans beginnen oft mit einem Verb oder können nur Verb sein 
(isLocked, locked, ...), bei Zahlen oder Strings ist das aber meistens 
anders (amountOfFails, motorCurrent, userName, ...).
Egal wie man es macht, so richtig richtig ist es nie, da kann man 
genausogut alles klein schreiben.

Funktionen/Methoden drücken oft eine Tätigkeit aus, bestehen 
sinnvollerweise aber oft aus mehr als einem Verb und beinhalten oft ein 
Objekt (im grammatikalischen Sinne von Subjekt, Verb und Objekt) 
(flush(), getFoo(), setFoo(), sayHelloWorld(), ...)
In camelCase-Schreibweise erspart man sich den lästigen '_', den ich 
persönlich gräßlich finde, und hat dennoch eine Trennung zwischen den 
Namensbestandteilen. Und fangen trotzdem klein an.


Aber so richtig weiß man solche Schreibweisen erst zu schätzen, wenn man 
mal einige 10.000 Zeilen Code damit geschrieben hat. Nicht jede 
Konvention ist sinnvoll, aber die von Java gefällt mir gut genug um sie 
auch in C zu verwenden.

von Walter T. (Gast)


Lesenswert?

Boolesche Variablen ā la "isLocked" fand ich immer unlogisch, weil das 
wichtigste hinten steht. Da finde ich die kanadische Notation besser:
1
a = lockedEh ? 10 : 20;

von A. S. (Gast)


Lesenswert?

Walter T. schrieb:
> Da finde ich die kanadische Notation besser

?

> lockedEh

?

von Wühlhase (Gast)


Lesenswert?

Walter T. schrieb:
> Boolesche Variablen ā la "isLocked" fand ich immer unlogisch, weil das
> wichtigste hinten steht.

Ich ziehe mir die Variablennamen auch nicht nach subjektiv empfundener 
Wichtigkeit aus dem Fingern. Zwischen Verb und Adverb die Wichtigkeit 
auszudifferenzieren führt auch zu nichts: ob du 'is' oder 'locked' 
wegnimmst, beides ist sinnentstellend.

In erster Linie versuche ich Code so zu schreiben, daß ich ihn wie 
Fließtext lesen kann. Das erspart überflüssige Kommentare im Quelltext.

von Εrnst B. (ernst)


Lesenswert?

Zu stark (ab-)gekürzte Variablennamen führen, abhängig von der 
Dozenten-Köpergröße, zu Punktabzug:

"zwerg" für ZwischenErgebnis oder
"dwarf" für "data without any reasonable function"

von M.A. S. (mse2)


Lesenswert?

KArl Fred M. schrieb:
> Ja, mir gefällt die Ungarische Notation bislang auch am besten
Warum überrascht mich das nicht?

von tut nix zur sache (Gast)


Lesenswert?

Ich finds ne gute Idee - auch in C - die gute alte Groß/Kleinschreibung 
zu nutzen: Klassen/structs groß schreiben (modellieren ja meist 
Objekte), Operationen/Funktionen (Tätigkeiten/Verben) auf diesen 
Objekten klein.

Nen Satz wie: es existiert ein Auto, bei dem der Starter betätigt wird 
modelliert sich z.B. zu:

Auto a;
a.startEngine();
a.engageClutch();
a.shiftUp();
a.disengageClutch();
a.stopEngine();

irgendsowas halt. In C könnte halt Auto ne struct sein und als Parameter 
rein:

startEngine(&a);
engageClutch(&a);
shiftUp(&a);
disengageClutch(&a);
stopEngine(&a);

-> guter Startpunkt ist Google Style, gibt aber auch ne Reihe andere, 
geeignete.

von Yalu X. (yalu) (Moderator)


Lesenswert?

tut nix zur sache schrieb:
> Ich finds ne gute Idee - auch in C - die gute alte Groß/Kleinschreibung
> zu nutzen: Klassen/structs groß schreiben (modellieren ja meist
> Objekte), Operationen/Funktionen (Tätigkeiten/Verben) auf diesen
> Objekten klein.

Sollte man nach dieser Logik nicht auch Variablen, insbesondere
Instanzen von Klassen, mit einem Großbuchstaben beginnen lassen? Bei
Enum-Elementen könnte man die Groß-/Kleinschreibung davon abhängig
machen, ob es sich um Substantive oder Adjektive handelt, also etwa so
(auch wenn das nicht mein Stil ist):
1
enum VehicleType { Car, Truck, Bike };
2
enum VehicleColor { black, white, red };
3
4
struct Vehicle {
5
  VehicleType Type;
6
  VehicleColor Color;
7
};
8
9
Vehicle Vehicle;

Alles nicht so einfach :)

Anders als in C und C++ nimmt einem Haskell zumindest bei der
Groß-/Kleinschreibung des Anfangsbuchstabens von Identifiern die
offensichtlich so schwere Entscheidung ab und regelt dies ganz
diktatorisch per Sprachspezifikation:

Mit einem Großbuchstaben beginnen die Namen von

- Modulen
- Typklassen
- Typkonstruktoren
- Typen
- Datenkonstruktoren

Mit einem Kleinbuchstaben beginnen die Namen von

- Typvariablen
- Funktionen
- Variablen

Wer gegen diese Regel verstößt, bekommt sofort Schelte vom Compiler :)

Für die restlichen Zeichen in Identifiern gibt es zwar keine strikte
Regel, aber eine allgemein akzeptierte Konvention, nämlich Camel Case
bzw. Pascal Case, so dass einem auch dort die Entscheidung abgenommen
wird.

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


Lesenswert?

Richtige Programmiersprachen haben sowieso alles groß geschrieben, außer 
Strings, aber die hießen dort auch noch "Hollerith-Konstante". ;-) In 
der beliebtesten (:-) Form dann auch gern als
1
22HDas ist eine Konstante aber das gehoert nicht mehr dazu

;-)

von MaWin (Gast)


Lesenswert?

Meine Religion verbietet Camel-Case. Was nun?

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


Lesenswert?

MaWin schrieb:
> Meine Religion verbietet Camel-Case. Was nun?

Wechsle entweder die Religion oder die Programmiersprache.

Moment: ist eine Programmiersprache nicht eh eine Religion? Bei dir ganz 
sicher.

von MaWin (Gast)


Lesenswert?

Jörg W. schrieb:
> Moment: ist eine Programmiersprache nicht eh eine Religion? Bei dir ganz
> sicher.

Da sieht man einmal wieder gut, dass du mich vollkommen falsch 
einschätzt.

Aus dem Alter in dem man religiöse Kriege um die "richtige" 
Quellcodeformatierung führt bin ich lange raus.
Viel wichtiger, als die "richtige" Formatierung zu wählen, ist eine 
konsistente Formatierung beizubehalten.

von Walter T. (nicolas)


Lesenswert?

Welche Zeilenlänge ist eigentlich heutzutage sinnvoll? Immer noch 80 
Zeichen, 100 Zeichen oder gar 120 Zeichen?

von Euro (Gast)


Lesenswert?

tut nix zur sache schrieb:
> Nen Satz wie: es existiert ein Auto, bei dem der Starter betätigt wird
> modelliert sich z.B. zu:
Was ist dann z.B. mit Properties in C#?
Z.B.: car.motorAlign = front; (???)

Ok, da liegt ein getter/setter hinter, aber der ist schon klein 
geschrieben.

von Rolf M. (rmagnus)


Lesenswert?

Walter T. schrieb:
> Welche Zeilenlänge ist eigentlich heutzutage sinnvoll? Immer noch 80
> Zeichen, 100 Zeichen oder gar 120 Zeichen?

In meinen Projekten gibt es keine harte Grenze, aber länger als 120 
sollte man möglichst vermeiden. Soll heißen: Wenn die Zeile mal 122 
Zeichen lang ist, muss man sie nicht gleich irgendwie auf zwei Zeilen 
verteilen, nur weil die Grenze halt bei 120 liegt. Generell finde ich 
Regeln, die ein hartes Limit setzen, selten sinnvoll.
Die harte Begrenzung auf 80 war im letzten Jahrtausend noch sinnvoll, 
als noch im Textmodus gearbeitet wurde, wo eben nur genau 80 Zeichen pro 
Zeile auf den Bildschirm passten.

: Bearbeitet durch User
von Teo D. (teoderix)


Lesenswert?

Walter T. schrieb:
> Welche Zeilenlänge ist eigentlich heutzutage sinnvoll? Immer noch 80
> Zeichen, 100 Zeichen oder gar 120 Zeichen?

So breit, das zwei Listings nebeneinander und die IDE auf meinen 27" 
passt, ohne das ich ne Lupe brauche oder großartig Horizontal scrollen 
muss. Wenn's mir zu bunt wird, breche ich die Zeile um. Ne wirklich 
feste Länge hab ich nicht.

von MaWin (Gast)


Lesenswert?

Walter T. schrieb:
> Welche Zeilenlänge ist eigentlich heutzutage sinnvoll?

In meiner Religion müssen Zeilen immer exakt 98 Zeichen lang sein. Nicht 
länger und nicht kürzer!

Aber im Ernst: Es spielt gar keine Rolle. Wenn mir dein Format nicht 
passt, dann formatiere ich es mit einem der seit Jahrzehnten 
existierenden Code-Reformatiertools um.
Wenn du gerne horizontal scrollst, dann mache es bitte.
Ich mache es nicht und begrenze mich deshalb auf in etwa 90-100 Zeichen.

von MaWin (Gast)


Lesenswert?

Und außerdem hängt das von der Sprache ab.
Je nach Sprache kann es ja manchmal sinnvoll sein schon nach 20 Zeichen 
umzubrechen.
1
fizz.foobar().
2
     bizbazz().
3
     barrdurr().
4
     bummdi().
5
     dummdi().
6
     ladi().
7
     dadi();

von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> Aber im Ernst: Es spielt gar keine Rolle. Wenn mir dein Format nicht
> passt, dann formatiere ich es mit einem der seit Jahrzehnten
> existierenden Code-Reformatiertools um.

Das ist wenig sinnvoll, wenn man mit mehreren Leuten an einem 
gemeinsamen Repository arbeitet.

> Wenn du gerne horizontal scrollst, dann mache es bitte.

Bei mir bricht der Editor es bei der Darstellung einfach um, wenn man 
über den Rand kommt. Das ist zwar nicht sehr hübsch, erspart einem aber 
das Scrollen. Wobei ich zumindest mit dem Desktop-Monitor bei 120 
Zeichen noch problemlos zwei Files nebeneinander bekomme. Auf dem 
Bildschirm des Laptop reicht's dann aber nicht mehr ganz.

von Walter T. (nicolas)


Lesenswert?

Ich glaube, wir bleiben bei C.

Ich habe üblicherweise 100 Zeichen als Grenze. Dann passen auf einem 
38-Zoll-Monitor noch drei Merge-Fenster nebeneinander.

Das Problem: Variablennamen sind heute deutlich länger als, damals, als 
Variablennamen allerhöchstens zwei Buchstaben Länge haben sollten, und 
dann ist mit einem billigen y = (x+x0)*a; schon ruck-zuck eine ganze 
Zeile übervoll. Beispiel:
1
    int32_t dro0_um = sataddmulwrn_s32(This->Slow.dro0Raw_um, This->Main.dro0ZeroOffset_um, SIGN(Prm->dro0Scale));
Noch schlimmer werden Funktions-Signaturen. Das sind fast immer 
Mehrzeiler, obwohl mir nirgendwo etwas auffällt, was sinnvoll gekürzt 
werden sollte. Willkürliches Beispiel aus dem Fenster vor mir:
1
    int_fast8_t menu_standard(constflash Menuitem_t Menudata[],
2
                        constflash Menuconfig_t *Menuconfig,
3
                        int_fast8_t selectedItem);
Testweise habe ich mal 120 Zeichen ausprobiert, aber das ist 
gleichzeitig vom Lesefluss zu breit und für Funktionssignaturen zu 
schmal.

von MaWin (Gast)


Lesenswert?

Rolf M. schrieb:
> Das ist wenig sinnvoll, wenn man mit mehreren Leuten an einem
> gemeinsamen Repository arbeitet.

Genau. Denn wie ich bereits schrieb:

MaWin schrieb:
> Viel wichtiger, als die "richtige" Formatierung zu wählen, ist eine
> konsistente Formatierung beizubehalten.

Walter T. schrieb:
> Das Problem: Variablennamen sind heute deutlich länger als, damals

Das ist natürlich auch nur ein Problem der Selbstdisziplin.

Walter T. schrieb:
> int_fast8_t menu_standard(constflash Menuitem_t Menudata[],
>                         constflash Menuconfig_t *Menuconfig,
>                         int_fast8_t selectedItem);
1
#define cflash constflash // irgendwo zentral.
2
3
int8_t menu_std(cflash MenuItem_t data[],
4
                cflash MenuConf_t *cfg,
5
                int8_t selItem);

Die ganze fast-Typen-wichserei bringt praktisch keinen Laufzeitgewinn, 
aber verschlechtert die Lesbarkeit enorm und birgt auch Möglichkeiten 
für versteckte Fehler.

von Walter T. (nicolas)


Lesenswert?

Die "fast"-Typen sind für mich eine Absichtserklärung: "Ich brauche 8 
Bit Breite, aber ich verlasse mich nicht auf irgendwelchen Overflow."

Welche versteckten Fehler können sie erzeugen?

von J. S. (jojos)


Lesenswert?

72 war doch das Limit, die letzten 8 Zeichen sind für die Nummerierung 
der Lochkarten reserviert.

von MaWin (Gast)


Lesenswert?

Walter T. schrieb:
> Die "fast"-Typen sind für mich eine Absichtserklärung: "Ich brauche 8
> Bit Breite, aber ich verlasse mich nicht auf irgendwelchen Overflow."

Dann nimm doch einfach 'int'. Weniger Tipparbeit, auch mindestens 8 Bit 
breit und von der tatsächlichen Größe her auch implementation defined.

> Welche versteckten Fehler können sie erzeugen?

Wenn dein Code eben doch Überläufe erzeugt, weil er zum Beispiel Bugs 
hat, dann hängt das Verhalten und ob UB auftritt von der tatsächlichen 
Größe ab. Schwere Debugbarkeit. Schlechtere Lesbarkeit. Außerdem 
unterscheidet sich das Cast-Verhalten und das Ergebnis wird 
Plattformabhängig (s.u.). Fast-Typen haben praktisch nur Nachteile.
Du könntest hier auch einfach 'int' verwenden. Oder halt uint8_t.
1
#include <stdint.h>
2
#include <stdio.h>
3
4
int main(void)
5
{
6
        uint16_t a = 0xFFFF;
7
        int16_t b;
8
        int_fast16_t c;
9
10
        b = (int16_t)a;
11
        c = (int_fast16_t)a;
12
13
        printf("%d %d\n%d %d %d\n", sizeof(b), sizeof(c), (int)a, (int)b, (int)c);
14
}

Ausgabe:
1
2 8
2
65535 -1 65535

Wenn jetzt eine Plattform sich entscheiden würde int_fast16_t 
tatsächlich als int16_t zu implementieren, was ja erlaubt ist und z.B. 
auf AVR8 wahrscheinlich der Fall sein dürfte, dann wäre die Ausgabe:
1
2 2
2
65535 -1 -1

von A. S. (Gast)


Lesenswert?

Walter T. schrieb:
> Welche Zeilenlänge ist eigentlich heutzutage sinnvoll? Immer noch 80
> Zeichen, 100 Zeichen oder gar 120 Zeichen?

Das hängt (wie alles andere) von Werkzeug und Arbeitsstil ab.

Mancher Code ist im "Blocksatz" besser lesbar. Das füllen von 10 structs 
mit gleichen, fortlaufenden und systematischen Inhalten kann im 
Blocksatz viel einfacher kontrolliert werden. Also 10 lange Zeilen 
untereinander. Das gleiche bei manchen if/else.

Wenn dein Werkzeug in für Dich üblicher konfug 80 Zeichen darstellt, 
kann es beim meisten Code sinnvoll sein, die Kommentare hinter die 
Anweisung zu schreiben.

Bei 30 Zeichen (weil zumeist im Debugger und 3 Quelltexte gleichzeitig 
oder einfach schlechte Augen) dann halt über der Zeile.

Die festen Grenzen kommen aus Zeiten fester Werkzeuge (Lochkarte, 
Textmonitor)

von Walter T. (nicolas)


Lesenswert?

Ich verstehe Deinen Standpunkt in Bezug auf die "fast" und 
"least"-Datentypen. Ich muss mal überlegen, ob ich künftig die gleichen 
Schlüsse daraus ziehe.

Wie sieht es bei den Kurznamen aus?

Was mir aufgefallen ist: "Config" wurde auf zwei verschiedene Arten 
abgekürzt, nämlich "Conf" und "Cfg". Ein weiterer Kandiat, den ich schon 
gesehen habe, wäre "Cnf", noch nie gesehen in freier Wildbahn: "Cnfg".

Für mich war der Schluss daraus: "Schreib es aus. Du kannst schnell 
tippen. Du kannst schnell lesen. Das ist am wenigsten fehlerträchtig."

Wie hält man das konsistent? Gibt es da einen Thesaurus, mit denen die 
Profis gängige Bezeichnungen abkürzen?

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Walter T. schrieb:
> Was mir aufgefallen ist: "Config" wurde auf zwei verschiedene Arten
> abgekürzt, nämlich "Conf" und "Cfg".

Sehr gut erkannt. War mir gar nicht aufgefallen. Das sollte natürlich 
noch verbessert werden.
Die genaue Wahl, ob conf, cfg, cnf oder meinetwegen auch config finde 
ich dabei gar nicht so wichtig. Eher, dass es überall konsistent und 
gleich ist. (Was ja hier bei mir nicht der Fall war.)

Variablenlängen addieren sich ja oft auf in der Zeile. Deshalb finde ich 
es wichtig in Variablennamen nicht unnötig zu "schwätzen". Das Wort 
"menu" in Variablennamen finde ich in der Funktion, bei der es nur um 
Menüs geht, beispielsweise unnötig. Die Variablennamen "menuConfig" und 
"config" sind vom Informationsgehalt in dem Kontext gleichwertig, aber 
config ist kürzer und deshalb würde ich es wählen (und dann ggf. noch 
weiter abkürzen zu etwa conf oder cfg.)

von MaWin (Gast)


Lesenswert?

Achja und vielleicht wäre statt
1
cflash MenuItem_t data[],

sowas hier
1
cflash MenuItem_t items[],

besser, falls dieser Parameter ein Array der möglichen Menuitems 
darstellen soll. Das ist zwar ein Zeichen länger, aber deutlich genauer 
beschreibend.

von Fenner (Gast)


Lesenswert?

Walter T. schrieb:
> Welche Zeilenlänge ist eigentlich heutzutage sinnvoll? Immer noch 80
> Zeichen, 100 Zeichen oder gar 120 Zeichen?

Als Alleinprogrammierer nehme ich 80 Zeichen als Grenze, wobei ich mit 
Kommentaren auch mal darüber hinaus gehe. Insbesondere bei 
Member-Variablen von Klassen, da habe ich die Variablen gerne als Liste 
untereinander, das ist mir wichtig für den Überblick. Die Variablen 
bekommen dann eine kurze Beschreibung, die dann in der gleichen Zeile 
dahinter steht und die 80 Zeichen reichen dann oft nicht. Macht aber ja 
nichts, die Beschreibung schaut man nicht oft an, da kann man auch mal 
nach rechts scrollen oder das Fenster größer ziehen.
Mit "echtem" Code gehe ich aber nie über die 80 Zeichen.

von Mark B. (markbrandis)


Lesenswert?

Walter T. schrieb:
> Noch schlimmer werden Funktions-Signaturen. Das sind fast immer
> Mehrzeiler

Und das Problem daran ist... was genau?

von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> Rolf M. schrieb:
>> Das ist wenig sinnvoll, wenn man mit mehreren Leuten an einem
>> gemeinsamen Repository arbeitet.
>
> Genau. Denn wie ich bereits schrieb:
>
> MaWin schrieb:
>> Viel wichtiger, als die "richtige" Formatierung zu wählen, ist eine
>> konsistente Formatierung beizubehalten.

Du hast aber auch geschrieben:

MaWin schrieb:
> Wenn mir dein Format nicht passt, dann formatiere ich es mit einem der
> seit Jahrzehnten existierenden Code-Reformatiertools um.

Und das setzt eben voraus, dass ihr nicht gemeinsam an dem Code 
arbeitet.

MaWin schrieb:
> Walter T. schrieb:
>> Die "fast"-Typen sind für mich eine Absichtserklärung: "Ich brauche 8
>> Bit Breite, aber ich verlasse mich nicht auf irgendwelchen Overflow."
>
> Dann nimm doch einfach 'int'. Weniger Tipparbeit, auch mindestens 8 Bit
> breit und von der tatsächlichen Größe her auch implementation defined.

Aber auf einem AVR halt langsamer und speicherintensiver.

> Wenn dein Code eben doch Überläufe erzeugt, weil er zum Beispiel Bugs
> hat, dann hängt das Verhalten und ob UB auftritt von der tatsächlichen
> Größe ab. Schwere Debugbarkeit. Schlechtere Lesbarkeit. Außerdem
> unterscheidet sich das Cast-Verhalten und das Ergebnis wird
> Plattformabhängig (s.u.).

Das gilt für int aber auch.

> Fast-Typen haben praktisch nur Nachteile.

Sie haben den Vorteil, dass du nicht eine feste Größe erzwingst, wo du 
sie gar nicht brauchst. Es gibt präziser an, was du benötigst. Und außer 
bei Hardware-Registern und Binärformaten braucht man nur selten Typen, 
die eine ganz bestimmte feste Größe haben müssen. Stattdessen hat man 
Mindestanforderungen und möchte eben entweder einen auf geringe Laufzeit 
oder einen auf minimale Größe optimierten Typ, je nachdem, ob man jetzt 
in einer Schleife 100 Millionen mal ein und das selbe Objekt des Typs 
beschreibt oder ob man ein Array aus 100 Millionen Objekten benötigt. 
Genau das drücken int_fast*_t und int_least*_t aus.

> Du könntest hier auch einfach 'int' verwenden. Oder halt uint8_t.
> #include <stdint.h>
> #include <stdio.h>
> int main(void)
> {
>         uint16_t a = 0xFFFF;
>         int16_t b;
>         int_fast16_t c;
>         b = (int16_t)a;
>         c = (int_fast16_t)a;
>         printf("%d %d\n%d %d %d\n", sizeof(b), sizeof(c), (int)a,
> (int)b, (int)c);
> }
>
> Ausgabe:2 8
> 65535 -1 65535
>
> Wenn jetzt eine Plattform sich entscheiden würde int_fast16_t
> tatsächlich als int16_t zu implementieren, was ja erlaubt ist und z.B.
> auf AVR8 wahrscheinlich der Fall sein dürfte, dann wäre die Ausgabe:2 2
> 65535 -1 -1

Dein Argument ist also, dass fehlerhafte Werte auftreten können, wenn 
dein Programm Fehler hat? Im übrigen hättest du mit int exakt das selbe 
Problem. Denn auch der ist in der Regel auf dem AVR 16 Bit breit und auf 
dem PC größer.

MaWin schrieb:
> Variablenlängen addieren sich ja oft auf in der Zeile. Deshalb finde ich
> es wichtig in Variablennamen nicht unnötig zu "schwätzen". Das Wort
> "menu" in Variablennamen finde ich in der Funktion, bei der es nur um
> Menüs geht, beispielsweise unnötig. Die Variablennamen "menuConfig" und
> "config" sind vom Informationsgehalt in dem Kontext gleichwertig, aber
> config ist kürzer und deshalb würde ich es wählen (und dann ggf. noch
> weiter abkürzen zu etwa conf oder cfg.)

Das entspricht auch die Regel, dass Namen umso aussagekräftiger sein 
sollen, je größer der Scope ist, in dem sie genutzt werden.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Rolf M. schrieb:
> Aber auf einem AVR halt langsamer und speicherintensiver.

Was meinen Vorschlag die Typen mit plattformunabhängiger Größe zu 
verwenden nur untermauert. Mein Vorschlag zu int statt int_fast8_t war 
nur, falls man unbedingt einen Typ mit plattformdefinierter Größe haben 
will.

Rolf M. schrieb:
> Dein Argument ist also, dass fehlerhafte Werte auftreten können, wenn
> dein Programm Fehler hat?

Nein. Das habe ich nie gesagt. Ich habe das Gegenteil gesagt.
Ich sagte, dass Fehler mit int_fast8_t (und Konsorten) leichter zu 
produzieren sind und schwerer zu finden sind, als mit intX_t.
Dass das Programm fehlerhaft ist, ist unbestritten und Absicht.
Es ging mir darum warum das Programm fehlerhaft ist.

Rolf M. schrieb:
> Im übrigen hättest du mit int exakt das selbe Problem.

Ganz genau. Deshalb Typen fester Breite.

Du hängst dich hier am int fest, ohne verstanden zu haben, was ich damit 
in einem Nebensatz gesagt habe. Das war ein völlig unwichtiges 
Randdetail in meiner Argumentation.

Wir sind einer Meinung, nur du hast es noch nicht bemerkt.

von Walter T. (nicolas)


Lesenswert?

Mark B. schrieb:
> Walter T. schrieb:
>> Noch schlimmer werden Funktions-Signaturen. Das sind fast immer
>> Mehrzeiler
>
> Und das Problem daran ist... was genau?

Das ist eine gute Frage, und ich habe jetzt mehr als 10 Minuten darüber 
nachgedacht, ohne eine echte Antwort zu finden.

Es erzeugt ein.....Unwohlsein.

Vielleicht liegt es nur daran, dass in allen Büchern, die ich 
mittlerweile über Softwareentwicklung gelesen habe, alle 
Funktions-Signaturen grundsätzlich schicke Einzeiler sind, und das sich 
als gefühlter SOLL-Zustand eingenistet hat.

Aber vielleicht ist das tatsächlich nur der Unterschied zwischen der 
schönen Theorie und der schmutzigen Praxis.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Teo D. schrieb:
> Walter T. schrieb:
>> Welche Zeilenlänge ist eigentlich heutzutage sinnvoll? Immer noch 80
>> Zeichen, 100 Zeichen oder gar 120 Zeichen?
>
> So breit, das zwei Listings nebeneinander

Besser drei (für Three-Way-Merge). Bei einer minimalen horizontalen
Bildschirmauflösung von 1920 Pixel sind gerade etwa 3×80 Zeichen
möglich, ohne dass die Zeichen pixelig wirken. Für Programme in C,
Python und Haskell sind die 80 Zeichen auch völlig ausreichend, bei C++
wird es etwas grenzwertig.

Wenn ich in Projekten mit anderen arbeite und es dafür einen Style-Guide
gibt, richte ich mich natürlich nach diesem. Der Editor wird dann
automatisch mit den jeweiligen Parametern gestartet. Da ist die maximale
Zeilenlänge dann oft 120, was auch für C++ adäquat ist und auf einem
Full-HD-Display immerhin noch zwei Listings nebeneinander zulässt.

Zeilenumbrüche sollte man nur dort machen, wo es auch logisch sinnvoll
ist. Gibt es in einer langen Zeile keine guten Umbruchpositionen, ist es
besser, eine lange, komplizierte Anweisung in zwei einfachere zu
zerlegen.

Sinnvoll umgebrochene Zeilen oder in mehrere Einzelanweisungen
aufgeteilte Anweisungen habe auch mehr Struktur. Eine überlange Zeile
ist in sich strukturlos und muss deswegen vom Leser mit dem Auge geparst
werden, was auf Dauer sehr anstrengend sein kann.

Von Formatierungstools, die an den Zeilenumbrüchen herumdoktern, halte
ich nicht viel, weil sie die Zeilen irgendwo, aber selten an logisch
sinnvollen Stellen umbrechen.

Überlange Zeilen sind oft die Folge von überlangen Variablennamen.
Weiter oben habe ich geschrieben:

Yalu X. schrieb:
> Je größer der Scope, desto aussagekräftiger der Name.
>
> Je kleiner der Scope, desto kürzer der Name.

Setzt man Variablen mit weitem Scope (insbesondere globale Variablen)
mit Bedacht ein, fördert das nicht nur die allgemeine Übersichtlichkeit,
sondern vermeidet auch überlange Zeilen.

von Michael D. (nospam2000)


Lesenswert?

KArl Fred M. schrieb:
> @PittyJ
> Ja, mir gefällt die Ungarische Notation bislang auch am besten

Wer sich schon mal darauf verlassen hat, dass die Prefixe der 
ungarischen Notation auch korrekt verwendet werden (und z.B. bei 
Typänderungen auch nachgezogen werden) um dann nach einiger Zeit der 
Fehlersuche festzustellen zu müssen, dass die inkorrekt war, wird sie 
nie wider verwenden.

Zentrale Regel beim Entwickeln: Redundanz die manuell abgeglichen wird 
muss vermieden werden. Da die ungarische Notation dies nicht tut ist sie 
Mist.

 Michael

von loeti2 (Gast)


Lesenswert?

Ich schreibe meine Programme immer in SciTE in Proportionalschrift.
(Da sich ein Compiler der mit Formatierung einer Textverarbeitung 
zurecht kommt noch nicht durchsetzen konnte. Siehe mein letzter Beitrag 
im Thread)

Deshalb ist die maximale Zeilenlänge von der Breite der genutzten 
Buchstaben abhängig.
Als kleiner Nachteil sehe ich dass das Untereinanderstellen z.B. von 
Parametern bei Funktionen schwierig ist. Siehe hier die Zeile mit 
unsigned long long c), da muß man mit Leerzeichen kreativ werden.

[tab][tab]void realBigfooFunction(unsigned long long a, unsigned long 
long b,

[tab][tab][spc][spc]...[spc][spc][spc]unsigned long long c) {

[tab][tab][tab]...

[tab][tab]}

von A. S. (Gast)


Lesenswert?

Walter T. schrieb:
> Es erzeugt ein.....Unwohlsein.

Nicht nur. He nach Werkzeugen kann es sein, dass Einzeiler Vorteile 
haben. Z.b. wenn man die Funktion per Textsuche sucht (warum auch immer) 
und das Ergebnis im suchfenster nur einzeilig ist.

Bei SW kommt es nur auf Lesbarkeit an. Und Lesbarkeit ist auch davon 
abhängig, ob man Begriffe direkt erklärt bekommt (suche, mouseover, ...) 
oder erst dahin springen muss.

von Jobst Q. (joquis)


Lesenswert?

KArl Fred M. schrieb:
> und wie unterscheidet ihr globale von lokalen Variablen z.B.

Lokale Variablen immer klein und so kurz wie möglich. Oft vorkommende 
Standardvariablen wie i, s und t erleichtern die Wiederverwertung.

Globale Variablen fangen groß an, gerne als CamelCase, ebenso 
Funktionen, die  globalen Variablen verändern. Es gibt keinen Grund, 
keine Variablen groß zu beginnen, und die deutliche Unterscheidung von 
lokalen und globalen Variablen halte ich für wesentlich, um schnell 
wieder den Überblick zu finden.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Walter T. schrieb:
> Noch schlimmer werden Funktions-Signaturen. Das sind fast immer
> Mehrzeiler, obwohl mir nirgendwo etwas auffällt, was sinnvoll gekürzt
> werden sollte. Willkürliches Beispiel aus dem Fenster vor mir:
> int_fast8_t menu_standard(constflash Menuitem_t Menudata[],
>                         constflash Menuconfig_t *Menuconfig,
>                         int_fast8_t selectedItem);
> Testweise habe ich mal 120 Zeichen ausprobiert, aber das ist
> gleichzeitig vom Lesefluss zu breit und für Funktionssignaturen zu
> schmal.

Ich formatiere sowas gerne so:
1
int_fast8_t menu_standard(
2
  constflash Menuitem_t Menudata[],
3
  constflash Menuconfig_t *Menuconfig,
4
  int_fast8_t selectedItem
5
);

Das kann man selbst bei 10 Argumenten noch gut lesen.

von J. S. (jojos)


Lesenswert?

Name in Großbuchstaben, nur am Anfang und Ende klein, warum hat man 
sowas gemacht?

von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> Rolf M. schrieb:
>> Dein Argument ist also, dass fehlerhafte Werte auftreten können, wenn
>> dein Programm Fehler hat?
>
> Nein. Das habe ich nie gesagt. Ich habe das Gegenteil gesagt.

Es ist genau das, was dein Beispiel aussagt. Dein Programm enthält einen 
Fehler, nämlich die Annahme, dass int_least16_t größer als 16 Bit ist. 
Deshalb kommt auf Plattformen, wo das nicht gilt, ein falscher Wert 
raus.

> Ich sagte, dass Fehler mit int_fast8_t (und Konsorten) leichter zu
> produzieren sind und schwerer zu finden sind, als mit intX_t.

Das finde ich nicht.

> Dass das Programm fehlerhaft ist, ist unbestritten und Absicht.

Das ist mir schon klar.

> Es ging mir darum warum das Programm fehlerhaft ist.

> Wir sind einer Meinung, nur du hast es noch nicht bemerkt.

Nein. Ich bin der Meinung, dass die fast- und least-Typen sinnvoll sind, 
du  offenbar nicht.

von MaWin (Gast)


Lesenswert?

Rolf M. schrieb:
> Dein Programm enthält einen
> Fehler, nämlich die Annahme, dass int_least16_t größer als 16 Bit ist.

Du hast es immer noch nicht verstanden.
Es ging nicht um den Fehler ansich und auch nicht darum was genau der 
Fehler ist.
Es ging darum, dass bestimmte Aktionen (casten) mit Verwendung der 
Fast-Typen auf einmal plattformabhängig werden. Und dass das eventuell 
schwieriger Im Griff zu behalten ist. Es ist schwieriger damit ein 
korrektes Programm zu schreiben.

Jetzt verstanden?

Rolf M. schrieb:
> Ich bin der Meinung, dass die fast- und least-Typen sinnvoll sind,

Dann begründe das doch mal.
Und nein, "alles wird magisch schneller" ist keine. Denn das ist nicht 
der Fall.

von Walter T. (nicolas)


Lesenswert?

Naja, explizites casten ist eine Aktion, die bei mir eigentlich recht 
selten vorkommt. Und dann kommt auch kein klassischer "int" dabei vor, 
sondern irgendein Typ fester Breite.

Warum sollte man einen int_fastX_t überhaupt auf einen Datentyp kleiner 
x Bit casten wollen?

von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> Es ging darum, dass bestimmte Aktionen (casten) mit Verwendung der
> Fast-Typen auf einmal plattformabhängig werden. Und dass das eventuell
> schwieriger Im Griff zu behalten ist. Es ist schwieriger damit ein
> korrektes Programm zu schreiben.
>
> Jetzt verstanden?

Das ist schon klar, dass du das meintest. Nur trägt das Beispiel dazu 
nicht sonderlich bei.

> Rolf M. schrieb:
>> Ich bin der Meinung, dass die fast- und least-Typen sinnvoll sind,
>
> Dann begründe das doch mal.

Habe ich doch bereits. Es drückt genauer aus, was der Programmierer 
will, was in der Regel eben nicht ein Typ mit exakt n Bits Größe ist, 
sondern einer, der bestimmten Mindestanforderungen genügt.

> Und nein, "alles wird magisch schneller" ist keine. Denn das ist nicht
> der Fall.

Es lässt dem Compiler die Wahl, welcher Typ an der Stelle am besten 
geeignet ist.

von Udo K. (udok)


Lesenswert?

MaWin schrieb:
> Wenn jetzt eine Plattform sich entscheiden würde int_fast16_t
> tatsächlich als int16_t zu implementieren, was ja erlaubt ist und z.B.
> auf AVR8 wahrscheinlich der Fall sein dürfte, dann wäre die Ausgabe:

Hier bei mir (x64 Win10), ist int_fast16_t 16-Bit breit.

Die Fast Typen machen das Programm eher langsamer.  Der Compiler muss 
zwischen unterschiedlichen integer Typen konvertieren.  Und wenn 
int_fast16_t wirklich 64-Bit ist, dann braucht das unnötig Speicher 
(Instructions sind länger und 4 facher Cache Bedarf).  Einheitlich "int" 
zu verwenden ist leichter lesbar und oft schneller.  printf funktioniert 
auch nicht mehr richtig ohne Cast Orgien...
1
#include <stdint.h>
2
int foo_int(int a, int b) { return a + b; }
3
int_fast16_t foo_fast16(int_fast16_t a, int_fast16_t b) { return a + b; }
4
int foo_mix(int a, int_fast16_t b) { return a + b; }
5
int64_t foo64(int64_t a, int64_t b) { return a + b; }

Liefert mit einem betagten MS cl compiler (der noch immer verwendet 
wird, weil getestet):
1
File Type: COFF OBJECT
2
3
foo_int:
4
  0000000000000000: 8D 04 11           lea         eax,[rcx+rdx]
5
  0000000000000003: C3                 ret
6
7
foo_fast16:
8
  0000000000000000: 0F BF C1           movsx       eax,cx
9
  0000000000000003: 0F BF CA           movsx       ecx,dx
10
  0000000000000006: 03 C1              add         eax,ecx
11
  0000000000000008: C3                 ret
12
13
foo_mix:
14
  0000000000000000: 0F BF C2           movsx       eax,dx
15
  0000000000000003: 03 C1              add         eax,ecx
16
  0000000000000005: C3                 ret
17
18
foo64:
19
  0000000000000000: 48 8D 04 11        lea         rax,[rcx+rdx]
20
  0000000000000004: C3                 ret

Mit einem aktuellen clang
1
foo_int:
2
  0000000000000000: 8D 04 11           lea         eax,[rcx+rdx]
3
  0000000000000003: C3                 ret
4
5
foo_fast16:
6
  0000000000000000: 8D 04 0A           lea         eax,[rdx+rcx]
7
  0000000000000003: C3                 ret
8
9
foo_mix:
10
  0000000000000000: 0F BF C2           movsx       eax,dx
11
  0000000000000003: 01 C8              add         eax,ecx
12
  0000000000000005: C3                 ret
13
14
foo64:
15
  0000000000000000: 48 8D 04 11        lea         rax,[rcx+rdx]
16
  0000000000000004: C3                 ret

von Udo K. (udok)


Lesenswert?

Yalu X. schrieb:
> Besser drei (für Three-Way-Merge). Bei einer minimalen horizontalen
> Bildschirmauflösung von 1920 Pixel sind gerade etwa 3×80 Zeichen
> möglich, ohne dass die Zeichen pixelig wirken. Für Programme in C,
> Python und Haskell sind die 80 Zeichen auch völlig ausreichend, bei C++
> wird es etwas grenzwertig.

Ich versuche hier auch, unter 80 Zeichen zu bleiben.  Bei C++ werden es 
manchmal auch etwas mehr.  Damit kann ich mehrere Files nebeneinander 
optisch vergleichen.  Und manchmal wird das Zeugs ja auch noch 
ausgedruckt abgelegt.

von Udo K. (udok)


Lesenswert?

Rolf M. schrieb:
>
> Habe ich doch bereits. Es drückt genauer aus, was der Programmierer
> will, was in der Regel eben nicht ein Typ mit exakt n Bits Größe ist,
> sondern einer, der bestimmten Mindestanforderungen genügt.

Das hat man doch auch mit "int".  Ist ja nichts anderes als ein integer 
mit mindestens 16 Bit Breite laut Standard.  Und am PC auf allen 
relevanten Systemen 32 Bit.

Den einzigen integer Typ, den ich vermeide ist "long".  Der ist auf 
unterschiedlichen PC Systemen entweder 32 Bit (Windows), oder 64 Bit 
(Linux).
Das macht nur Probleme.

> Das ist schon klar, dass du das meintest. Nur trägt das Beispiel dazu
> nicht sonderlich bei.
>

Eigentlich ist das Beispiel perfekt.  Genau solche Fehler werden in der 
Praxis andauernd passieren.

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


Lesenswert?

Rolf M. schrieb:
> Es lässt dem Compiler die Wahl, welcher Typ an der Stelle am besten
> geeignet ist.

Insbesondere compiliert etwas überhaupt noch auf einer Plattform, die 
ein uint8_t nicht abbilden kann (weil sie bpsw. nur 32-Bit-Einheiten 
überhaupt kennt). Wenn man außerdem Code bspw. zwischen ARM und AVR 
portabel gestalten will, erzwingt uint8_t auf einem ARM oft genug 
schlechteren Code (Maskierungen) als uint_fast8_t, während es auf dem 
AVR keine Rolle spielt.

Aber uint_fast8_t in "ungarischer" Notation wird bestimmt ein lustiges 
Geschreibsel. ;-)

von Wolfgang (Gast)


Lesenswert?

PittyJ schrieb:
> f_Counter = 1;
>
> Da weiss ich sofort, der Counter ist vom Type Float.

Eigentlich solltest du bei so etwas sofort wissen, dass grundlegend noch 
ein Wurm in dem Programm ist. Da kräuseln sich einem die Fußnägel.

von Udo K. (udok)


Lesenswert?

Jörg W. schrieb:
> Aber uint_fast8_t in "ungarischer" Notation wird bestimmt ein lustiges
> Geschreibsel. ;-)

cbFoo = cbBar + cbZoo;

Ist nicht so schwierig.  Richtige Ungarische Notation kodiert nicht den 
Typ,
sondern die Bedeutung (cb = Count of Bytes).

Und wenn dann da steht:

cbBoo = cchBar + cbZoo;

Dann weisst du sofort:  Da ist ein Bug drinnen!
Ich kann keinen cb (Count of Bytes) mit einem cch (Count of Characters) 
vermischen.

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


Lesenswert?

Udo K. schrieb:

> Ist nicht so schwierig.  Richtige Ungarische Notation kodiert nicht den
> Typ,
> sondern die Bedeutung (cb = Count of Bytes).

Warum muss ich bei einem Counter festlegen, dass ich Bytes zähle? Was 
ist, wenn ich Objekte zähle? Was, wenn ich einen Zeiger auf das Objekt 
"Speicherbereich" habe, aber ihm dann einen Zeiger auf ein Objekt 
"Gerätetyp" zuweise? (Mal kurz zwei Beispiele aus AVRDUDE.) Was mache 
ich für Bedeutungen, die sich Herr Simonyi nicht vorstellen konnte?

von Oliver S. (oliverso)


Lesenswert?

Rolf M. schrieb:
> Es lässt dem Compiler die Wahl, welcher Typ an der Stelle am besten
> geeignet ist.

Nur um der eventuellem Mißinterpretation vorzubeugen, daß der Compiler 
da in Abhängigkeit des Kontextes Typen auswählen kann:

Es gibt der Implementierung auf einer Plattform die Möglichkeit, einen 
passenden Typ festzulegen. Der Compiler hat keine Wahl bzw. weiß 
überhaupt nichts davon. Der benutzt an allen Stellen für einen fast_int 
den gleichen Typ.

Oliver

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Udo K. schrieb:
> cbBoo = cchBar + cbZoo;
> Dann weisst du sofort:  Da ist ein Bug drinnen!

In vernünftigen Sprachen regelt man das über das Typsystem und nicht 
über die Variablennamen.
In C mit seinem primitiven Typsystem bleibt einem natürlich nichts 
anderes übrig, als sich solche hässlichen Krücken auszudenken.

von Udo K. (udok)


Lesenswert?

Jörg W. schrieb:
> Warum muss ich bei einem Counter festlegen, dass ich Bytes zähle? Was
> ist, wenn ich Objekte zähle? Was, wenn ich einen Zeiger auf das Objekt
> "Speicherbereich" habe, aber ihm dann einen Zeiger auf ein Objekt
> "Gerätetyp" zuweise? (Mal kurz zwei Beispiele aus AVRDUDE.) Was mache
> ich für Bedeutungen, die sich Herr Simonyi nicht vorstellen konnte?

Musst du ja nicht.  Die UN ist ja nur eine Möglichkeit mehr 
Typ-Sicherheit einzubauen.  Zähler und Index in Arrays sind meist 
integer Typen, und daher kannst du die bunt durcheinanderwürfeln, und 
der Compiler macht nicht mal eine Warnung. Mit der UN beseitigst du 
dieses Typdefizit, und siehst sofort, ob eine Code-Zeile von den 
Semantik her stimmen kann.
Üblicherweise stimmt was nicht, wenn du sowas siehst:
1
cbStrLength = cchStrLength   // sizeof(byte) != sizeof(character)
2
...
3
size_t cchFileName = strlen(pszFileName);
4
...
5
memcpy(pAvrDudeDest, pAvrDudeSource, cchFileName);    // what the fuck?
6
memcpy(pAvrDudeDest, pAvrDudeSource, cAvrDudeSource);     // Uhps
7
memcpy(pAvrDudeDest, pAvrDudeSource, cbAvrDudeSource);  // besser
8
...
9
strcpy(pszDest, pSource); // Uhhps
10
..
11
memcpy(pszDest, pszSource, cchSource); // Uhps
12
memcpy(pszDest, pszSource, cbSource);  // besser
13
...

Mit modernem C++ kann man für solche Dinge sicher besser Template 
Klassen verwenden.
1
...
2
CCount<AVRDUDE> cAvrDude;
3
...
4
CCount<wchar_t> cch;
5
...
6
CopyAvrDudeArray(pAvrDudeDest, pAvrDudeSource, cch);  // Compiler Error
7
...
8
CopyAvrDudeArray(pAvrDudeDest, pAvrDudeSource, cAvrDude);  // besser
9
...
10
cAvrDude = cch;  // Compile Error
11
...

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


Lesenswert?

Oliver S. schrieb:
> Der benutzt an allen Stellen für einen fast_int den gleichen Typ.

Das stimmt auch schon eine Weile nicht mehr.

Beispiel:
1
#include <stdint.h>
2
#ifndef TYPE
3
#  define TYPE int_fast16_t
4
#endif
5
6
char x[20];
7
8
int num_x(void) {
9
  TYPE i;
10
  int count = 0;
11
  for (i = 0; i < sizeof(x) / sizeof(x[0]); i++)
12
    if (x[i] > 0) count++;
13
14
  return count;
15
}

Mal mit drei verschiedenen Typdefinitionen compiliert:
1
$ avr-gcc -Os -mmcu=atmega328 -S -o default.s test.c
2
$ avr-gcc -Os -mmcu=atmega328 -DTYPE=int -S -o int.s test.c
3
$ avr-gcc -Os -mmcu=atmega328 -DTYPE=int_fast32_t -S -o int_fast32_t.s test.c
4
$ md5sum *.s                                                          d1c7804aedae7e8006e7e0adaf7a3b0f  default.s
5
d1c7804aedae7e8006e7e0adaf7a3b0f  int.s
6
d1c7804aedae7e8006e7e0adaf7a3b0f  int_fast32_t.s

Identische Ergebnisse. ;-)

von Udo K. (udok)


Lesenswert?

Bestätigt doch, das er immer "int" intern verwendet...

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


Lesenswert?

Udo K. schrieb:
> Bestätigt doch, das er immer "int" intern verwendet...

Nein, wenn der Wertebereich von 32 bit nötig wäre (oder er es nicht 
ermitteln kann), müsste er für den letzten Fall mehr als "int" nehmen 
(das auf dem AVR ja nur 16 bits hat).

Wenn er ermitteln kann, was passend ist (hier: durch die Anzahl der 
Array-Elemente vorgegeben), kann er entdprechend optimieren.

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


Lesenswert?

Intern nimmt er hier übrigens einen Zeiger …

von Udo K. (udok)


Lesenswert?

Jörg W. schrieb:
> Wenn er ermitteln kann, was passend ist (hier: durch die Anzahl der
> Array-Elemente vorgegeben), kann er entdprechend optimieren.

Ok, jetzt sehe ich es :-)

Das ist für Compiler heute kein Problem zum wegoptimieren.

Sonst müsste ja auch jeder Typ, der kleiner als ein int ist, erst mal 
auf int konvertiert werden (Integer Promotion). Damit würden alle 
Berechnungen mit kleineren Typen massiv benachteiligt werden.

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


Lesenswert?

Udo K. schrieb:
> Das ist für Compiler heute kein Problem zum wegoptimieren.

Ja. Es widerspricht einfach nur obiger Behauptung, dass der real 
verwendete Typ von vornherein irgendwie im Compiler festgezurrt wäre.

von Udo K. (udok)


Lesenswert?

Jörg W. schrieb:
> enn er ermitteln kann, was passend ist (hier: durch die Anzahl der
> Array-Elemente vorgegeben), kann er entdprechend optimieren.

Ich habe das auf dem PC ausprobiert.

clang-cl -O1 macht da den kleinsten Code mit int, auch wenn es nur um 
ein paar Bytes geht (int: 42 Bytes, int_fast16_t: 47 Bytes).

MS cl 2008 genauso, da ist der Unterschied 33 zu 39 Bytes.

MS cl 2022 macht keinen Unterschied: immer 34 oder 57 Bytes (-O1 / -O2).

Wenn ich bei clang-cl -O2 angebe, dann macht der loop unrolling -
What the fuck - Code size: int=133 Bytes, int_fast16_t=133 Bytes).

von Udo K. (udok)


Lesenswert?

Jörg W. schrieb:
>> Das ist für Compiler heute kein Problem zum wegoptimieren.
>
> Ja. Es widerspricht einfach nur obiger Behauptung, dass der real
> verwendete Typ von vornherein irgendwie im Compiler festgezurrt wäre.

Der Compiler muss nur sicherstellen, dass sich der Code so verhält, als 
würde er die Standard Regeln einhalten (inklusive integer Promotion). 
Bei Konstanten ist das recht einfach, oder wenn alle Variablen denselben 
Typ haben.

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


Lesenswert?

Udo K. schrieb:
> Ich habe das auf dem PC ausprobiert.

Da sind die Register mittlerweile 64 Bit breit, da kannst du solche 
Effekte schwerer erkennen.

von Oliver S. (oliverso)


Lesenswert?

Jörg W. schrieb:
> Oliver S. schrieb:
>> Der benutzt an allen Stellen für einen fast_int den gleichen Typ.
>
> Das stimmt auch schon eine Weile nicht mehr.

Ja, aber das ist völlig unabhängig von den fast_/least-*-Typen.

Jörg W. schrieb:
> Ja. Es widerspricht einfach nur obiger Behauptung, dass der real
> verwendete Typ von vornherein irgendwie im Compiler festgezurrt wäre.

Da habe ich mich vielleicht mißverständlich ausgedrückt. Die 
fast-/least-Typen werden als typedefs auf <unsigned> 
char/short/int/long/... von der Implementierung festgezurrt.

Andere Typen kennt der Compiler gar nicht.

Oliver

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


Lesenswert?

Oliver S. schrieb:

> Andere Typen kennt der Compiler gar nicht.

Dann wird dich überraschen, wie das beim AVR aussieht. ;-)
1
typedef signed int int8_t __attribute__((__mode__(__QI__)));
2
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
3
typedef signed int int16_t __attribute__ ((__mode__ (__HI__)));
4
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));
5
typedef signed int int32_t __attribute__ ((__mode__ (__SI__)));
6
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));

Offensichtlich kennen zumindest manche Compiler durchaus andere Typen. 
;-)

Aber ja, der Sinn ist natürlich, dass jede Implementierung für jede 
ihrer Plattformen den passenden Typen damit abstrahieren kann.

: Bearbeitet durch Moderator
von Oliver S. (oliverso)


Lesenswert?

Jörg W. schrieb:
> Offensichtlich kennen zumindest manche Compiler durchaus andere Typen.
> ;-)

Der gezeigte kennt überhaupt nur nur signed/unsigned int ;)
(Ok, mit ein paar nicht-standardkonformen Ergänzungen).

Oliver

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Es gibt beim gcc & clang noch __int128_t und bei c23 _BitInt(N) (Wobei 
es für N eine obergrenze gibt, über der das ib ist.)

von Rolf M. (rmagnus)


Lesenswert?

Udo K. schrieb:
> Rolf M. schrieb:
>>
>> Habe ich doch bereits. Es drückt genauer aus, was der Programmierer
>> will, was in der Regel eben nicht ein Typ mit exakt n Bits Größe ist,
>> sondern einer, der bestimmten Mindestanforderungen genügt.
>
> Das hat man doch auch mit "int".

Ja, aber int will MaWin ja auch nicht.

von MaWin (Gast)


Lesenswert?

Jörg W. schrieb:
> Das stimmt auch schon eine Weile nicht mehr.

Das ist eine ganz normale as-if Optimierung. Mit der Sprachsemantik auf 
Typebene hat das absolut nichts zu tun.
Wenn der Compiler beweisen kann, dass er mit einem anderen Typ 
effizienter zum gleichen Ergebnis kommen kann ohne das extern sichtbare 
Verhalten zu ändern, dann darf er natürlich das intern machen.
Damit, wie Fast-Typen definiert sind, hat das gar nichts zu tun.
Ganz im Gegenteil. Die as-if Optimierungen sind der Hauptgrund dafür, 
warum die Fast-Typen unnötig sind. Ein moderner Compiler kann viel 
optimieren. Vor allem mit LTO.
Fast-Typen sind ein Relikt vergangener Zeiten.

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


Lesenswert?

🐧 DPA 🐧 schrieb:
> bei c23 _BitInt(N)

Wobei die ja wieder komplett anderes Verhalten haben.

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.