Forum: Mikrocontroller und Digitale Elektronik crc-Berechnung Codezeile Erklärung


von Matthias S. (mat-sche)


Lesenswert?

Liebes Forum

ich habe hier eine Codezeilen die ich nicht ganz verstehe und würde mich 
über eine kurze Erklärung freuen:
1
#include "CRC16.h"
2
#include "CRC.h"
3
CRC16 crc;
4
void test1()
5
{
6
  static char buff[23];
7
  snprintf(buff, sizeof(buff),"[%s/%s/%d,%d,%d,]","A","Index",strlen(buff),buttonstate_index[0],buttonstate_index[1]);
8
  Serial.print("strlen(buff)= ");
9
  Serial.println(strlen(buff));
10
  Serial.print("buff=  ");          
11
  Serial.println(buff);                                                                                         // Daten senden  
12
  Serial.println("" );
13
  Serial.print("crc16=  ");  
14
  Serial.println(crc16((uint8_t *) buff, sizeof(buff), 0x1021, 0, 0, false, false), HEX);

"Serial.println(crc16((uint8_t *) buff, sizeof(buff), 0x1021, 0, 0, 
false, false), HEX);"

Um diese Zeile geht es. Wie bekomme ich das Ergebnis bzw. die Hex-Zahl 
in eine Variable, die ich dann weiter verarbeiten kann
? Und welche Größe müsste diese haben?

Vielen Dank für die Hilfe!

von Stefan F. (Gast)


Lesenswert?

Matthias S. schrieb:
> crc16((uint8_t *) buff, sizeof(buff), 0x1021, 0, 0,
> false, false)

uint8_t meineVariable = crc16((uint8_t *) buff, sizeof(buff), 0x1021, 0, 
0, false, false)

von Adam P. (adamap)


Lesenswert?

Du brauchst eine 16Bit Variable.
uint16_t oder unsigned short.

Und dann nimmst du die crc16() Funktion einfach aus der println 
heraus...

Vorher:
1
Serial.println(crc16((uint8_t *) buff, sizeof(buff), 0x1021, 0, 0, false, false), HEX);

Nachher:
1
unsigned short my_crc16;
2
3
my_crc16 = crc16((uint8_t *) buff, sizeof(buff), 0x1021, 0, 0, false, false);
4
Serial.println(my_crc16, HEX);

von Adam P. (adamap)


Lesenswert?

Stefan ⛄ F. schrieb:
> uint8_t meineVariable

Wie kommst du auf uint8_t?

von Stefan F. (Gast)


Lesenswert?

Adam P. schrieb:
> Wie kommst du auf uint8_t?

Das ist falsch. Das Ergebnis muss natürlich eine 16 Bit Variable sein.

Ich möchte noch ergänzen: Um eine Integer Variable in einen 
Hexadezimalen String umzuwandeln, kann man sprintf() benutzen.
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#ga6017094d9fd800fa02600d35399f2a2a
1
char puffer[10];
2
sprintf(puffer, "%04X", variable);

0: die Zahl soll ggf mit Nullen beginnen
4: ist die Anzahl der gewünschten Hex-Ziffern
X: Hexadezimal mit großen Buchstaben (alternativ geht auch x für kleine 
Buchstaben)

von Matthias S. (mat-sche)


Lesenswert?

> Stefan ⛄ F. schrieb:
> Adam P. schrieb:
Super! VIELEN DANK.
Ich habe mir es gestern schon so gedacht, war mir leider nicht sicher, 
da es zu keinem vernüftigen Ergenis kam in meinem Code kam.
1
Serial.println(crc16((uint8_t *) buff, sizeof(buff), 0x1021, 0, 0, false, false), HEX);

Bedeutet also nur, dass "(uint8_t *) buff" uint8_t* ein Zeiger auf den 
Wert ist, der in buff steht?
Und was ist besser, sizeof(buff) oder strlen(buff) zur bestimmung der 
Länger der in buff befindlichen Zeichen zu ermitteln?

von Jim M. (turboj)


Lesenswert?

Matthias S. schrieb:
> Und was ist besser, sizeof(buff) oder strlen(buff) zur bestimmung der
> Länger der in buff befindlichen Zeichen zu ermitteln?

Das kommt daraf an(tm).

Nämlich ob die Eingabe ein String variabler Länge ist - und die 
Nullbytes nicht mitzählen - oder ein fester Puffer, wo auch Null Bytes 
wichtig sein könn(t)en.

von Stefan F. (Gast)


Lesenswert?

Matthias S. schrieb:
> Bedeutet also nur, dass "(uint8_t *) buff" uint8_t* ein Zeiger auf den
> Wert ist, der in buff steht?

Fast.

Es bedeutet, dass der Zeiger auf einen (oder mehrere) uint8 zeigt. Man 
braucht das, wenn der Zeiger in Wirklichkeit auf etwas anderes zeigt, 
als was die Funktion haben will.

Letztendlich zeigen alle Zeiger auf Zellen im RAM*, das man als eine 
Folge von Bytes verwenden kann.

*) Ja ich weiß, es gibt Ausnahmen.

von Matthias S. (mat-sche)


Lesenswert?

Jim M. schrieb:
> Nämlich ob die Eingabe ein String variabler Länge ist - und die
> Nullbytes nicht mitzählen - oder ein fester Puffer, wo auch Null Bytes
> wichtig sein könn(t)en.

Was würde das heißen? Wie kann ich dieses Nullbyte erkennen? :)
Nein schon klar, aber was geht nun bei
1. variabler Länge
2. fester Länge

Ich habe auch ein Verständnisproblem mit dem Nullbyte, bei einer 
seriellen Datenübertragung wird am Ende immer ein Nullbyte an den 
Datenstring mit angehängt? Und wenn ja, wie kann ich dies z.Bsp. in 
einem Terminalprogramm mir anzeigen lassen?
Wie ist es mit dem Nullbyte, wenn ich seriell Daten in einen Puffer 
einlese, muss ich ja die Puffergröße immer +1 festlegen. Wenn ich nun 
die Puffergröße ermitteln möchte, wie geh ich dann vor?

von Stefan F. (Gast)


Lesenswert?

Matthias S. schrieb:
> was geht nun bei
> 1. variabler Länge
> 2. fester Länge

1: strlen(), welches die Anzahl der belegten Bytes zählt, wobei die 
abschließende 0 nicht mitgezählt wird
2: sizeof(), welches die Anzahl der Bytes von Argument schon beim 
Compilieren weis.
1
char variable[100]="Hallo";

strlen(variable) ist 5, weil der String 5 Zeichen lang ist. Tatsächlich 
sind 6 Zeichen belegt, wegen der abschließenden Null.

sizeof(variable) ist 10, weil das Array 10 bytes groß ist. Der Inhalt 
spielt keine Rolle.

Wenn du ein Array mit variablem Inhalt hast, der nicht mit einer 0 
terminiert ist, dann geht keins von beiden. Dann must du selbst wissen, 
wie groß der Inhalt ist, also eine eigene Variable dafür benutzen.

von Arno (Gast)


Lesenswert?

Jim M. schrieb:
> Nämlich ob die Eingabe ein String variabler Länge ist - und die
> Nullbytes nicht mitzählen - oder ein fester Puffer, wo auch Null Bytes
> wichtig sein könn(t)en.

Und ob buff ein Array oder ein Pointer ist (wozu Arrays speziell bei der 
Übergabe als Funktionsparameter gern degenerieren) und welchen Datentyp 
buff hat.

Bei char wird dank sizeof(char) = 1 (per Definition) das zweite Problem 
wohl nur auf eher exotischen Plattformen auftreten, auf denen char mehr 
als 8 Bits hat (z.B. ist bei 16-Bit-char sizeof(buff) vermutlich halb so 
groß wie die Anzahl der uint8_t, die die Funktion verarbeiten soll) und 
dann ist fraglich, ob eine solche Plattform überhaupt uint8_t kennt. Bei 
den diversen "wide character"-Datentypen wird das auch auf gängigen 
Plattformen potentiell lustig.

MfG, Arno

von Stefan F. (Gast)


Lesenswert?

Matthias S. schrieb:
> Ich habe auch ein Verständnisproblem mit dem Nullbyte, bei einer
> seriellen Datenübertragung wird am Ende immer ein Nullbyte an den
> Datenstring mit angehängt?

Das kommt ganz drauf an, wie du die Kommunikation programmierst. Die 
Serielle Schnittstelle überträgt bytes, sie weiss nicht was ein String 
ist und die konkreten Werte sind ihr egal.

Üblicherweise terminiert man die Zeilen bei Klartext-Schnittstellen mit 
einem Zeilenumbruch im Unix Format (\n), traditionell ist auch das alte 
DOS Format \r\n noch relativ weit verbreitet.

> Und wenn ja, wie kann ich dies z.Bsp. in einem Terminalprogramm
> mir anzeigen lassen?

Kommt auf dein Programm an. Manche Zeigen Null-Zeichen gar nicht an. 
hammer Terminal zeigt sie als Kästchen mit Nullen drin an.

> Wie ist es mit dem Nullbyte, wenn ich seriell Daten in einen Puffer
> einlese, muss ich ja die Puffergröße immer +1 festlegen.

Ja

> Wenn ich nun die Puffergröße ermitteln möchte, wie geh ich dann vor?

Die Größe des Puffers ist eine Sache, wie viel davon belegt wurde ist 
eine andere. Siehe oben mein Beispiel mit dem "Hallo".

von Arno (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> sizeof(variable) ist 10, weil das Array 10 bytes groß ist. Der Inhalt
> spielt keine Rolle.

In deinem Beispiel
1
char variable[100]="Hallo";
ist sizeof(variable) 100. Ist sicher ein Tippfehler, aber bevor die 
Verwirrung zu groß wird...

MfG, Arno

von Stefan F. (Gast)


Lesenswert?

Arno schrieb:
> Ist sicher ein Tippfehler, aber bevor die
> Verwirrung zu groß wird...

Oh ja, danke für's Aufpassen.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Arno schrieb:
> und
> dann ist fraglich, ob eine solche Plattform überhaupt uint8_t kennt

Den kann sie nicht kennen, denn was wäre dann sizeof(uint8_t)? sizeof 
arbeitet in Vielfachen von char, d.h. es kann keinen kleineren (in 
Sachen Speicherverbrauch) Datentyp als char geben.

von Arno (Gast)


Lesenswert?

Niklas G. schrieb:
> Arno schrieb:
>> und
>> dann ist fraglich, ob eine solche Plattform überhaupt uint8_t kennt
>
> Den kann sie nicht kennen, denn was wäre dann sizeof(uint8_t)? sizeof
> arbeitet in Vielfachen von char, d.h. es kann keinen kleineren (in
> Sachen Speicherverbrauch) Datentyp als char geben.

Klingt logisch, danke für die Ergänzung. Dann hat mich mein Gefühl nicht 
getrogen :)

MfG, Arno

von Stefan F. (Gast)


Lesenswert?

Gibt es überhaupt aktuelle (nicht historische) Systeme wo char mehr als 
8 Bit hat?

von Matthias S. (mat-sche)


Lesenswert?

@-ALL,

vielen Dank der Aufklärung, nun kann ich weiter machen :)!!!

{PS. [ von Stefan ⛄ F. (stefanus) ]
Danke für die Hilfe, würd ja gern Dir mal nen Pot Kaffee ausgeben, bin 
morgen in Berlin - Spandau :) }

von Matthias S. (mat-sche)


Lesenswert?

Dann hab ich noch eine Frage:
wenn ich es richtig sehe, wird bei der crc Berechnung in der Funktion 
mit String/Char-Array gearbeitet (berichtigt mich bitte wenn ich es 
falsch interpretiere)
[c]
  crc.setPolynome(0x1021);
  crc.add((uint8_t*)str, 9);
  Serial.println(crc.getCRC(), HEX);
[\c]
ich aber z.Bsp. 2 Byte habe, wie kann ich von diesen den crc berechnen?
Muss ich erst die Byte zu char machen?

von Stefan F. (Gast)


Lesenswert?

Matthias S. schrieb:
> bin morgen in Berlin - Spandau

Uh, das ist sehr weit weg von mir. Trotzdem danke für das Lob. Ich habe 
aber auch einen Rüffel für die beiden Flüchtigkeitsfehler 8 versus 16 
und 10 versus 100 verdient. C ist zwar nur mein Hobby, trotzdem sollte 
das nach so vielen Jahren nicht gleich doppelt in einem Thread 
passieren.

von Matthias S. (mat-sche)


Lesenswert?

Stefan ⛄ F. schrieb:
> Matthias S. schrieb:
>> bin morgen in Berlin - Spandau
>
> Uh, das ist sehr weit weg von mir. Trotzdem danke für das Lob. Ich habe
> aber auch einen Rüffel für die beiden Flüchtigkeitsfehler 8 versus 16
> und 10 versus 100 verdient. C ist zwar nur mein Hobby, trotzdem sollte
> das nach so vielen Jahren nicht gleich doppelt in einem Thread
> passieren.

Das ist nicht schlimm, zum Glück bin ich nicht soo blutfrischer Anfänger 
und wusste schon, wie es sein sollte.

> Uh, das ist sehr weit weg von mir.

Ohh da hab ich mich wohl vermacht, wenn ich mich nicht vermache gibt es 
auch einen fleißigen Helfer Stefan aus Berlin...

ok, dann bist Du aus Düsseldorf?! doch ein bissle weiter weg :)

von Stefan F. (Gast)


Lesenswert?

Matthias S. schrieb:
> ok, dann bist Du aus Düsseldorf?!

Ja

von Matthias S. (mat-sche)


Lesenswert?

Matthias S. schrieb:
> Dann hab ich noch eine Frage:
> wenn ich es richtig sehe, wird bei der crc Berechnung in der Funktion
> mit String/Char-Array gearbeitet (berichtigt mich bitte wenn ich es
> falsch interpretiere)
> [c]
>   crc.setPolynome(0x1021);
>   crc.add((uint8_t*)str, 9);
>   Serial.println(crc.getCRC(), HEX);
> [\c]
> ich aber z.Bsp. 2 Byte habe, wie kann ich von diesen den crc berechnen?
> Muss ich erst die Byte zu char machen?

@ Stefan,

könntest Du etwas mir davon näherbringen?
Übrigens... ein schöner Schwalbenschwanz, hab ich nur einmal in meinem 
Leben in freier Natur gesehen :)

von Stefan F. (Gast)


Lesenswert?

Matthias S. schrieb:
> könntest Du etwas mir davon näherbringen?

Das musst du in der Doku der CRC Klasse nachlesen.

> ein schöner Schwalbenschwanz

Den habe ich coloriert weil er beim Trocknen ganz grau wurde. Da ist 
ewig her, da war ich vielleicht 15.

von Matthias S. (mat-sche)


Lesenswert?

ok, Danke!

von Adam P. (adamap)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich habe
> aber auch einen Rüffel für die beiden Flüchtigkeitsfehler 8 versus 16
> und 10 versus 100 verdient.

Ach was
...tippfehler, schneller getippt, als gedacht ;-) passiert jedem mal.

Matthias S. schrieb:
> Das ist nicht schlimm, zum Glück bin ich nicht soo blutfrischer Anfänger
> und wusste schon, wie es sein sollte.

Dann hattest du bestimmt einfach nur einen dieser "Den Wald vor lauter 
Bäumen nicht sehen" Momenten :) das passiert auch jedem mal.

Funktionsaufruf innerhalb der Parameterliste.
1
Serial.println( crc16(...), HEX );

Also ich schreibe so etwas sehr ungerne.

Ich bevorzuge eher die Schreibweise mit extra Variablen:
1
uint16_t foo;
2
3
foo = get_something(...);
4
print(foo, HEX);

Anstatt:
1
print(get_somoeting(...), HEX);

Da es sehr zum verlesen leitet und irgendwie einfach zu viel auf einmal 
ist (in einer Zeile).

Da gibt es noch viel schlimmere Bsp.

Evtl. ist es Geschmackssache?

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Adam P. schrieb:
> uint16_t foo;
> foo = get_something(...);

Genau das würde ich vermeiden, weil: foo ist hier zwischenzeitlich 
uninitialisiert. Wenn zwischen Definition und erster Zuweisung viel Code 
ist, kann es schnell mal passieren dass man zwischendurch versehentlich 
"foo" ausliest und dann undefiniertes passiert. Variablen sollte man 
immer erst dann definieren, wenn man einen Wert für sie hat, und sie 
direkt damit initialisieren:
1
uint16_t foo = get_something (...);

Das bedeutet insbesondere auch, dass man die Variable im 
innerst-möglichen Scope definiert, also z.B. in die innerste Schleife 
o.ä. So kann der Wert nicht versehentlich später noch genutzt werden, 
wenn er gar nicht mehr gültig ist o.ä.

So vermeidet man Fehler, und kürzer ist es auch. Seit C99 muss man 
Variablen auch nicht mehr alle am Anfang der Funktion definieren, und 
das sollte man nutzen.

: Bearbeitet durch User
von Matthias S. (mat-sche)


Lesenswert?

Adam P. schrieb:
> Evtl. ist es Geschmackssache?

Niklas G. schrieb:
> Genau das würde ich vermeiden, weil:

Ich als Anfänger kann beide Seiten verstehen!
Darum ist es für Anfänger auch schwierig, sich in bestehende Beispiele 
einzuarbeiten, da die Schreibweise manigfaltig sein kann und dennoch zum 
Gleichen führt.
Das hat mich an c++ so abgeschreckt, zu verstehen, was alles in einer 
Zeile bedeutet und wie es "auseinander" zu nehmen ist. Auch wenn wieder 
viele stöhnen, da geht es bei Bascom einfacher, übersichtlicher daher.
Langsam steige ich jedoch weiter in die Materie ein und sehe jedoch so 
einige Vorteile, die mir teilweise bei Bascom verwehrt blieben.

Ich find's jedoch gut, dass ich hier Hilfe bekomme. Habe auch "Der C++ 
PROGRAMMIERER" aber darin werden solche Beispiele nicht gleich sichtbar 
dargelegt.

Nun kämpfe ich ersteinmal mit Strings und Arrays und deren 
Möglichkeiten... Wenn jemand noch ein übersichtliches Deutsch-Tutorial 
hat...

Danke!

von Adam P. (adamap)


Lesenswert?

Niklas G. schrieb:
> Adam P. schrieb:
>> uint16_t foo;
>> foo = get_something(...);
>
> Genau das würde ich vermeiden, weil: foo ist hier zwischenzeitlich
> uninitialisiert. Wenn zwischen Definition und erster Zuweisung viel Code
> ist, kann es schnell mal passieren dass man zwischendurch versehentlich
> "foo" ausliest und dann undefiniertes passiert.

Also möchtest du uns mitteilen, dass du in deinem Source, den Überblick 
über lokale und globale Variablen verlierst?

Also eine Funktion sollte nicht 1000 Zeilen lang sein, so das sie auch 
auf den Bildschirm passt.
Bei meiner Variante sieht man doch oben die Definitionen der Variablen 
die in dieser Funktion verwendet werden?!
Das muss man doch im Blick haben - das sind alles PUSH und POP Befehle.

Und wenn ne Funktion zu lang wird, dass man die Variablen aus den Augen 
verliert - dann ist sie einfach zu lang.

Stell dir vor hast ne Funktion die 3 Parameter erwartet,
willst du dann etwa sowas schreiben:
1
// Lieber nicht
2
draw("Hallo", get_element_pos("TITEL"), get_head_color(), get_head_font());
3
4
// schon eher
5
pos_t xy;
6
uint32_t rgb;
7
font head_font;
8
9
xy = get_element_pos("TITEL");
10
rgb = get_head_color();
11
head_font = get_head_font();
12
13
draw("Hallo", xy, rgb, head_font);

Na ich weis ja nicht ob das so toll ist, wenn du das dann noch auf 
andere Dinge beziehst, wo der Funktionsaufruf in Augenkrebs 
endet...siehe Win-API.

Aber wie gesagt, jeder wie er mag!

> Wenn zwischen Definition und erster Zuweisung viel Code
> ist, kann es schnell mal passieren dass man zwischendurch versehentlich
> "foo" ausliest und dann undefiniertes passiert.
Ich verstehe deinen Einwand, aber das würde man nur machen, wenn es 
keinen Ausweg mehr gibt, weil die SW oder FW so verpfuscht wurde...ich 
kenn es.

: Bearbeitet durch User
von Niklas Gürtler (Gast)


Lesenswert?

Adam P. schrieb:
> Also möchtest du uns mitteilen, dass du in deinem Source, den Überblick
> über lokale und globale Variablen verlierst?

Es ging ausschließlich um lokale Variablen. Globale Variablen sollte man 
sowieso auch nicht nutzen.

Adam P. schrieb:
> Also eine Funktion sollte nicht 1000 Zeilen lang sein, so das sie auch
> auf den Bildschirm passt.

Sollte nicht, passiert aber schon mal.

Adam P. schrieb:
> Bei meiner Variante sieht man doch oben die Definitionen der Variablen
> die in dieser Funktion verwendet werden?!

Trotzdem ist es schwerer lesbar und fehleranfällig.

Adam P. schrieb:
> Das muss man doch im Blick haben - das sind alles PUSH und POP Befehle.

Hm? Der Compiler allokiert sowieso ein großes Stack Frame für alle 
lokalen Variablen beim Funktionseintritt, egal wo sie definiert sind.

Adam P. schrieb:
> willst du dann etwa sowas schreiben

Natürlich, ist schön kompakt und lesbar.

Adam P. schrieb:
> // schon eher

So schon gar nicht. Uninitialisierte Variablen, die man versehentlich 
verwenden kann. So wäre es auch ok:
1
pos_t xy = get_element_pos("TITEL");
2
uint32_t rgb = get_head_color();
3
font head_font = get_head_font(); draw("Hallo", xy, rgb, head_font);
In manchen Programmiersprachen (z.B. Kotlin, Rust, Scala) geht es 
überhaupt auch nur so, weil dort diese große Fehlerquelle, Variablen 
uninitialisiert zu lassen, gleich ganz verboten wird. In C++ versucht 
man mittels Konstruktoren auch dafür zu sorgen, dass immer alles sofort 
initialisiert wird.

Adam P. schrieb:
> Na ich weis ja nicht ob das so toll ist, wenn du das dann noch auf
> andere Dinge beziehst

Auch da kann man Variablen direkt initialisieren, wenn man sie nicht 
gerade per Out-Parameter initialisiert.

Adam P. schrieb:
> Ich verstehe deinen Einwand, aber das würde man nur machen, wenn es
> keinen Ausweg mehr gibt,

Man verändert Code ständig, und da können schnell Fehler passieren. 
Daher ist es etablierte Regel, eben diese Fehlerquelle zu vermeiden. In 
den meisten Programmiersprachen ist das auch absoluter Standard (oder 
eben Pflicht, s.o.), nur in C ist diese Trennung von Definition und 
Initialisierung noch so verbreitet, weil es eben bis C99 nicht anders 
ging.

von Adam P. (adamap)


Lesenswert?

Niklas Gürtler schrieb:
> Hm? Der Compiler allokiert sowieso ein großes Stack Frame für alle
> lokalen Variablen beim Funktionseintritt, egal wo sie definiert sind.

Ähm, NEIN.
Den gebe ich in meinen LinkerScripts an.

ABER das ist hier gar nicht das Thema!

von Adam P. (adamap)


Lesenswert?

Niklas Gürtler schrieb:
> So schon gar nicht. Uninitialisierte Variablen, die man versehentlich
> verwenden kann. So wäre es auch ok:
> pos_t xy = get_element_pos("TITEL");
> uint32_t rgb = get_head_color();
> font head_font = get_head_font(); draw("Hallo", xy, rgb, head_font);

Sorry, abar sowas ist bei mir ein NO-GO.

Deshalb benennt man ja Variablen auch demenstprechend.
Damit sie im Kontext zu erkennen sind...
Warum sollte ich z.b. "rgb" abfragen, wenn ich "rgb" noch nix
zugewiesen habe? Ergibt keinen Sinn.

von Niklas Gürtler (Gast)


Lesenswert?

Adam P. schrieb:
> Ähm, NEIN.
> Den gebe ich in meinen LinkerScripts an.

Bei welchem Compiler gibt man Stack-Frames im Linker-Script an? Alle mir 
bekannten Compiler summieren die Größen aller lokalen Variablen einer 
Funktion auf, und allokieren bei Funktionseintritt die entsprechende 
Menge auf dem Stack, z.B. mit einer SUB-Instruktion. Daher ist es für 
die Effizienz völlig unerheblich, wo in der Funktion die Variable 
definiert wird.

Adam P. schrieb:
> Sorry, abar sowas ist bei mir ein NO-GO.

Ist aber absolut üblich. Kompakter Code ist auch gut für die Lesbarkeit, 
denn schließlich gibt es einfach weniger zu überblicken. Natürlich 
sollte man es nicht übertreiben, wenn die Zeile zu lang wird kann man 
mit temporären Variablen anfangen, wie gezeigt.

Adam P. schrieb:
> Warum sollte ich z.b. "rgb" abfragen, wenn ich "rgb" noch nix
> zugewiesen habe? Ergibt keinen Sinn.

Weil Irren menschlich ist, und man bei nachträglicher Bearbeitung des 
Codes versehentlich die Variable zu früh auslesen könnte. 
Fehlervermeidung ist sehr wichtig.

Außerdem wird Code eben viel häufiger gelesen als geschrieben, und daher 
ist es wichtig, dass sofort zu erfassen ist, was da passiert. Wenn am 
Anfang der Funktion erstmal eine Liste an Variablen folgt, bringt das 
gar nichts - ich weiß nicht, was da rein geschrieben wird, wann sie 
gültig ist, wann nicht mehr... Wenn eine Variable z.B. nur in einer 
inneren Schleife benutzt wird, sollte man sie auch nur dort definieren 
und direkt initialisieren. Dann ist sofort ersichtlich, dass sie nur 
dort gültig ist, und man kann sie nicht versehentlich zu früh oder zu 
spät verwenden. Für die Effizienz macht das wie gesagt keinen 
Unterschied. Wie gesagt ist es in einigen Programmiersprachen gar nicht 
anders möglich oder nur als Ausnahme, weil schlaue Leute erkannt haben 
dass es so sicherer ist.

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.