Forum: Mikrocontroller und Digitale Elektronik Arraylänge falsch?


von Fragender (Gast)


Angehängte Dateien:

Lesenswert?

Ich frage mich gerade warum bei der Arraylänge nicht 5 raus kommt 
anstatt 6.
Seit wann wird da /0 dazugezaehlt?

:
von Einer K. (Gast)


Lesenswert?

Immer schon!

von A. S. (Gast)


Lesenswert?

Sizeof kennt keine Sonderbehandlung einer 0.

Strlen hingegen hört vor einer 0 auf.

Beitrag #5678830 wurde von einem Moderator gelöscht.
von Einer K. (Gast)


Lesenswert?

Glücklich ohne Grund schrieb im Beitrag #5678830:
> Ich meine es aber nicht böse.


Ich auch nicht..
Aber trotzdem sagt sizeof(t) von char t[]="Hello" eine Länge von 6 und 
strlen(t) eine Länge von 5

Da kannst du mit den Füßen auf dem Boden stampfen, wie du willst.
Blamierst dich nur ganz elendig.

Beitrag #5678832 wurde von einem Moderator gelöscht.
von A. S. (Gast)


Lesenswert?

Noch krasser ist der Unterschied, wenn du ein globales uninitialisiertes 
Array hast.

Dann liefert strlen 0

Und sizeof den reservierten Speicher in Bytes.

Beitrag #5678834 wurde von einem Moderator gelöscht.
von Fragender (Gast)


Lesenswert?

Danke für die Info.

Beitrag #5678837 wurde von einem Moderator gelöscht.
von M. K. (sylaina)


Lesenswert?

Glücklich ohne Grund schrieb im Beitrag #5678837:
> Von einem uninitialisierten Speicherbereich hätte ich jetzt auch nichts
> anderes erwartet.

Man muss halt wissen, wer was zurück liefert. Ich behaupten sogar: 
Solange ein globalen Array uninitialisiert ist, ist die Rückgabe von 
strlen unspezifiziert denn im Speicherbereich des uninitialisierten 
Arrays könnte ja auch "doof" drin stehen oder "Anton" oder sonstwas. Bei 
uninitialisierten Speicher sollte man nicht davon ausgehen, dass da 
überall "0" drin steht. ;)

Beitrag #5678844 wurde von einem Moderator gelöscht.
von Rolf M. (rmagnus)


Lesenswert?

M. K. schrieb:
> Glücklich ohne Grund schrieb:
>> Von einem uninitialisierten Speicherbereich hätte ich jetzt auch nichts
>> anderes erwartet.
>
> Man muss halt wissen, wer was zurück liefert. Ich behaupten sogar:
> Solange ein globalen Array uninitialisiert ist, ist die Rückgabe von
> strlen unspezifiziert denn im Speicherbereich des uninitialisierten
> Arrays könnte ja auch "doof" drin stehen oder "Anton" oder sonstwas. Bei
> uninitialisierten Speicher sollte man nicht davon ausgehen, dass da
> überall "0" drin steht. ;)

Der Knackpunkt ist, dass es in C eigentlich keine uninitialisierten 
globalen Variablen gibt. Wenn man sie nicht explizit initialisiert, 
werden sie implizit mit 0 initialisiert. Damit bringt strlen() immer 0 
zurück.

Glücklich ohne Grund schrieb im Beitrag #5678844:
> Das Problem an C ist halt die Nullterminierung. Mit einem Stringdeskriptor
> wäre das wieder ein ganz anderes Verhalten.

Und was soll da nun besser sein, wenn dort irgendein Zufallswert drin 
steht?

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

M. K. schrieb:
> Ich behaupten sogar:
> Solange ein globalen Array uninitialisiert ist, ist die Rückgabe von
> strlen unspezifiziert

In C werden globale Variablen automatisch mit 0 initialisiert, solange 
nichts anderes angegeben ist.

Daher liefert strlen in diesem Fall 0.

von Glücklich ohne Grund (Gast)


Lesenswert?

Rolf M. schrieb:

> Und was soll da nun besser sein, wenn dort irgendein Zufallswert drin
> steht?

Mit besser oder schlechter lässt sich das nicht ausdrücken. Als 
Programmierer muss ich wissen, was ich zu welcher Zeit an welchem Ort 
abfrage, und ob die Bedingungen einer Abfrage valide sind.

Wenn ein String Array bzw. ein Array von char angelegt wird, und mit 0 
initialisiert wird, dann wird die Stringlänge immer 0 sein. 
Vorausgesetzt strlen geht nach dem Nullbyte. Wenn keine 0 initialisiert 
wurde, ist es undefiniert.

Ich traue keiner Auto-Initialisierung in C. Dazu gibt es zu viele 
Unklarheiten. Wenn das Programm davon abhängig ist, dass bestimmte Werte 
initialisiert werden, dann tue ich das per Software, im setup(). Für 
nicht genutzten Speicher gibts kein Geld zurück. Einfache for-Schleife, 
wo ist das Problem?

von Rolf M. (rmagnus)


Lesenswert?

Glücklich ohne Grund schrieb:
> Wenn ein String Array bzw. ein Array von char angelegt wird, und mit 0
> initialisiert wird, dann wird die Stringlänge immer 0 sein.
> Vorausgesetzt strlen geht nach dem Nullbyte. Wenn keine 0 initialisiert
> wurde, ist es undefiniert.

Wenn du stattdessen irgendwo die Länge abspeicherst, hast du aber genau 
das gleiche Problem. Wenn das mit 0 initialisiert wurde, kommt auch eine 
Stringlänge von 0 raus, und wenn nicht, irgendein Blödsinn. Macht also 
keinen Unterschied.

> Ich traue keiner Auto-Initialisierung in C. Dazu gibt es zu viele
> Unklarheiten.

Welche? Die Regel ist einfach: Globale Variablen werden automatisch mit 
0 initialisiert, alles andere nicht.

von Glücklich ohne Grund (Gast)


Lesenswert?

Rolf M. schrieb:

> Welche? Die Regel ist einfach: Globale Variablen werden automatisch mit
> 0 initialisiert, alles andere nicht.

Oh täusche dich mal nicht. Gerade im Bereich Soft-Reset warten zuweilen 
Überraschungen, wo man keine erwartet hat.

von Glücklich ohne Grund (Gast)


Lesenswert?

Rolf M. schrieb:

> Wenn du stattdessen irgendwo die Länge abspeicherst, hast du aber genau
> das gleiche Problem. Wenn das mit 0 initialisiert wurde, kommt auch eine
> Stringlänge von 0 raus, und wenn nicht, irgendein Blödsinn. Macht also
> keinen Unterschied.

ja und nein. Bei VB kann ich z.B. sicher sein, dass jede Variable 
initialisiert ist. Bei C habe ich gelernt, das ist aber schon lange her, 
dass ICH die Variable initialisieren muss, ansonsten steht Zufall drin. 
Wenn sich das geändert hat, so viel habe ich mit C nicht zu tun, hängt 
es m.E. immer noch am Compiler, an der Version, am alter. Die selben 
Sourcen, unterschiedliches Verhalten. Bei anderen Sprachen kann ich es 
ausschließen, bei C aber nicht zu 100%. Und Programme mit 
Unsicherheitsfaktor erstelle ich nicht. Ich gehe davon aus, dass wir 
alle nbur von Arrays, struct & Co reden. "Normale" Variablen kann man 
mit =0 initialisieren, und das wird man normalerweise auch tun.

Beitrag #5678860 wurde von einem Moderator gelöscht.
von Mampf F. (mampf) Benutzerseite


Lesenswert?

Glücklich ohne Grund schrieb:
> Bei C habe ich gelernt, das ist aber schon lange her,
> dass ICH die Variable initialisieren muss, ansonsten steht Zufall drin.

Da muss man dann noch drüber nachdenken, ob zB ein Array global angelegt 
wurde.

Dann landet es - zumindest beim GCC - in der .bss Section, die beim 
Programmstart mit 0 initialisiert wird.

von Rolf M. (rmagnus)


Lesenswert?

Glücklich ohne Grund schrieb:
> Bei VB kann ich z.B. sicher sein, dass jede Variable
> initialisiert ist. Bei C habe ich gelernt, das ist aber schon lange her,
> dass ICH die Variable initialisieren muss, ansonsten steht Zufall drin.
> Wenn sich das geändert hat, so viel habe ich mit C nicht zu tun,

Die von mir beschriebene Regel gab es schon 1989, als C genormt wurde.

> hängt es m.E. immer noch am Compiler, an der Version, am alter. Die
> selben Sourcen, unterschiedliches Verhalten. Bei anderen Sprachen kann
> ich es ausschließen, bei C aber nicht zu 100%.

Wenn globale Variablen nicht implizit mit 0 initialisiert werden, hat 
der Compiler bzw. die Laufzeitumgebung einen Fehler. Kann man natürlich 
nicht ausschließen, aber das kann dir in anderen Sprachen dann genauso 
passieren.

: Bearbeitet durch User
von Glücklich ohne Grund (Gast)


Lesenswert?

Also ich hänge jede neue Struktur sofort in den Initialisierungslauf im 
setup(). Das ist mir in Fleisch und blut übergegangen und ich muss mir 
vor allem keine Gedanken machen. Bisher bin ich damit sehr gut gefahren. 
Lasst euch doch mal die millis() anzeigen. Das Compilieren dauert 35 S. 
Der Initialisierungslauf im aktuellen Programm läuft 800.92 mS. Bei über 
100 S. Quellcode. Da überlege ich nicht, ob ich initialisieren soll, 
sondern tus.

von Glücklich ohne Grund (Gast)


Lesenswert?

Rolf M. schrieb:

> Die von mir beschriebene Regel gab es schon 1989, als C genormt wurde.

Kann es sein, dass das vom OS abhängig ist? Ich habe damals auf UNIX 
gearbeitet.

von Walter K. (vril1959)


Lesenswert?

Der Pointer zeiger zeigt nicht auf ein anonymes Array - sondern auf ein 
compound literal

von Rolf M. (rmagnus)


Lesenswert?

Walter K. schrieb:
> Der Pointer zeiger zeigt nicht auf ein anonymes Array - sondern auf ein
> compound literal

Nein, er zeigt auf ein string literal, welches ein anonymes Array 
darstellt.
Ein compound literal wäre so:
1
char* zeiger = (char[]){ 'W', 'e', 'l', 't', '\0'};

Aber auch das wäre ein anonymes Array.

von Ein Gast (Gast)


Lesenswert?

Zum Thema Standard helfen vielleicht die Verweise hier weiter:
  http://c-faq.com/decl/initval.html

Glücklich ohne Grund schrieb:
> Der Initialisierungslauf im aktuellen Programm läuft 800.92 mS.

Wenn man maximal 250ms für die Initialisierung zur Verfügung hat, ist 
man damit leider nicht mehr innerhalb der Spezifikation.

von Glücklich ohne Grund (Gast)


Lesenswert?

Ein Gast schrieb:

> Wenn man maximal 250ms für die Initialisierung zur Verfügung hat, ist
> man damit leider nicht mehr innerhalb der Spezifikation.

Wenn man nur 250 mS "zur Verfügung" hat, dann hat man auch kein 
Riesenprogramm vor sich. So etwas gibt es nicht.

Walter K. schrieb:
> Der Pointer zeiger zeigt nicht auf ein anonymes Array - sondern auf ein
> compound literal

Ein compound literal. Aha. Sowas musste ja noch kommen. Ohne so einen 
Mist aus der hohen Theorie geht es hier nicht, oder? Ich bin dann weg.

von Dr. Sommer (Gast)


Lesenswert?

Glücklich ohne Grund schrieb:
> Also ich hänge jede neue Struktur sofort in den
> Initialisierungslauf im setup(). Das ist mir in Fleisch und blut
> übergegangen und ich muss mir vor allem keine Gedanken machen. Bisher
> bin ich damit sehr gut gefahren. Lasst euch doch mal die millis()
> anzeigen. Das Compilieren dauert 35 S. Der Initialisierungslauf im
> aktuellen Programm läuft 800.92 mS. Bei über 100 S. Quellcode. Da
> überlege ich nicht, ob ich initialisieren soll, sondern tus.

Arduino (danach klingt es) ist C++ und nicht C und das hat immer eine 
automatische Initialisierung, sonst würde da gar nichts funktionieren... 
C hat diese per Standard auch, aber es könnte irgendwo Umgebungen geben 
wo diese weggelassen wird - das wäre bei C++ halt komplett verkehrt. 
Alle globalen/statischen Variablen werden auf 0 initialisiert falls 
nicht anders per = angegeben. Auch Initialisierung per = wird effizient 
vom Startup Code durchgeführt (constant initialization). Daher ist das 
in setup() komplett redundant.
So einen popeligen AVR kann man in unter 1ms hochfahren. Wer da so viel 
Zeit verschwendet darf sich auch nicht beschweren wenn das Smartphone 5 
Minuten zum Starten brauchen...

von Rolf M. (rmagnus)


Lesenswert?

Glücklich ohne Grund schrieb:
> Ein Gast schrieb:
>
>> Wenn man maximal 250ms für die Initialisierung zur Verfügung hat, ist
>> man damit leider nicht mehr innerhalb der Spezifikation.
>
> Wenn man nur 250 mS "zur Verfügung" hat, dann hat man auch kein
> Riesenprogramm vor sich. So etwas gibt es nicht.

Das ist z.B. im Automotive-Bereich eine ganz normale Forderung für ein 
Steuergerät.

Übrigens sind es ms, nicht mS. S ist das Symbol für die Einheit für den 
Leitwert "Siemens".

von Walter K. (vril1959)


Lesenswert?

Rolf M. schrieb:
> Walter K. schrieb:
> Der Pointer zeiger zeigt nicht auf ein anonymes Array - sondern auf ein
> compound literal
>
> Nein, er zeigt auf ein string literal, welches ein anonymes Array
> darstellt.
> Ein compound literal wäre so:char* zeiger = (char[]){ 'W', 'e', 'l',
> 't', '\0'};
>
> Aber auch das wäre ein anonymes Array.

Selbstverständlich zeigt Zeiger in
char *zeiger = “Blah Blah”;
auf ein compount literal

Daran ändert Deine andere Schreibweise auch nix

Und ob man an dieser Stelle von einem anonymen Array sprechen kann, 
halte ich für gewagt!

von Rolf M. (rmagnus)


Lesenswert?

Walter K. schrieb:
> Selbstverständlich zeigt Zeiger in
> char *zeiger = “Blah Blah”;
> auf ein compount literal
>
> Daran ändert Deine andere Schreibweise auch nix

Die "andere Schreibweise" ist eine andere Art von literal. Eben kein 
compound literal, sondern ein string literal.

> Und ob man an dieser Stelle von einem anonymen Array sprechen kann,
> halte ich für gewagt!

Was soll es denn sonst sein? Es ist ein namenloses Objekt vom Typ "Array 
aus const char".

Hier mal der passende Aussschnitt aus ISO C (§6.5.2.5 Abschnitt 4):

"A postfix expression that consists of a parenthesized type name 
followed by a brace-enclosed list of initializers is a compound literal. 
It provides an unnamed object whose value is given by the initializer 
list."

Wo siehst du in "Blah Blah" einen parenthesized type name followed by a 
brace-enclosed list of initializers?

: Bearbeitet durch User
von Walter K. (vril1959)


Lesenswert?

Rolf M. schrieb:
> ...sondern ein string literal.
>
> ...
> Wo siehst du in "Blah Blah" einen parenthesized type name followed by a
> brace-enclosed list of initializers?

Du gibst die Antwort Doch selbst:
String Literal !

Beitrag #5679504 wurde von einem Moderator gelöscht.
von A. S. (Gast)


Lesenswert?

Glücklich ohne Grund schrieb:
> Also ich hänge jede neue Struktur sofort in den Initialisierungslauf im
> setup(). Das ist mir in Fleisch und blut übergegangen und ich muss mir
> vor allem keine Gedanken machen.

Das Funktioniert bei Anfängern recht zuverlässig. Sobald Du mehrere 
C-Dateien hast und über ints hinaus gehst, gibt es unter anderem 
folgende Probleme:

 * Die Variablen müssen global sein, oder es muss mehrere Setups geben
 * Das gleiche gilt auch analog für modul-Scope vs. Block-Scope
 * in Libraries gehen globale in einer Setup gar nicht (zumindest nicht 
in C, da dann immer alle Module dazugelinkt werden!)
 * Bei nicht trivialen Arrays oder Strukturen/Unions musst Du praktisch 
mit memcpy arbeiten.

Ganz schlimm wird es, wenn Du den globalen Wust dann auch mit anderen 
Dingen als mit 0 initialisierst. Dann kann niemand mehr Deinen Code 
nutzen.

Beitrag #5679640 wurde von einem Moderator gelöscht.
von M. K. (sylaina)


Lesenswert?

Ein Gast schrieb:
> Zum Thema Standard helfen vielleicht die Verweise hier weiter:
>   http://c-faq.com/decl/initval.html

Genau so hab ich das auch gelernt. Nur wenn ein static davor steht 
werden nicht explizit initialisierte Variablen mit 0 initialisiert.
Sind die Variablen nicht mit static gekennzeichnet und nicht 
initialisiert kann/darf man nicht sicher sein, dass sie mit 0 
initialisiert werden.

Ich möchte aber nicht ausschließen, dass sich das inzwischen geändert 
hat, ist bei mir ja jetzt schon über 30 Jahre her.

Beitrag #5679707 wurde von einem Moderator gelöscht.
Beitrag #5679714 wurde von einem Moderator gelöscht.
von Carl D. (jcw2)


Lesenswert?

M. K. schrieb:
> Ein Gast schrieb:
>> Zum Thema Standard helfen vielleicht die Verweise hier weiter:
>>   http://c-faq.com/decl/initval.html
>
> Genau so hab ich das auch gelernt. Nur wenn ein static davor steht
> werden nicht explizit initialisierte Variablen mit 0 initialisiert.
> Sind die Variablen nicht mit static gekennzeichnet und nicht
> initialisiert kann/darf man nicht sicher sein, dass sie mit 0
> initialisiert werden.

"static duration" bedeutet Variable, die nicht auf dem Stack liegt. Mit 
dem Keyword "static" kann man das innerhalb von Funktionen erzwingen. 
Außerhalb bedeutet "static" nur, daß die Variable nicht vom Linker aus 
anderen Compilation-Units aus referenziert werden kann ("nicht 
sichtbar").

Und "static duration" uninitialisiert kommt, soweit nicht durch 
Attribute anders gewünscht, in das .bss-Segment, das die Runtime bei 
jedem Start nullt.

> Ich möchte aber nicht ausschließen, dass sich das inzwischen geändert
> hat, ist bei mir ja jetzt schon über 30 Jahre her.

Das ist eher ein "static" Problem bei dir.  ;-)

: Bearbeitet durch User
Beitrag #5679758 wurde von einem Moderator gelöscht.
von Glücklich ohne Grund (Gast)


Lesenswert?

A. S. schrieb:
> Glücklich ohne Grund schrieb:
>> Also ich hänge jede neue Struktur sofort in den Initialisierungslauf im
>> setup(). Das ist mir in Fleisch und blut übergegangen und ich muss mir
>> vor allem keine Gedanken machen.
>
> Das Funktioniert bei Anfängern recht zuverlässig. Sobald Du mehrere
> C-Dateien hast und über ints hinaus gehst, gibt es unter anderem
> folgende Probleme:
>
>  * Die Variablen müssen global sein, oder es muss mehrere Setups geben
>  * Das gleiche gilt auch analog für modul-Scope vs. Block-Scope
>  * in Libraries gehen globale in einer Setup gar nicht (zumindest nicht
> in C, da dann immer alle Module dazugelinkt werden!)
>  * Bei nicht trivialen Arrays oder Strukturen/Unions musst Du praktisch
> mit memcpy arbeiten.
>
> Ganz schlimm wird es, wenn Du den globalen Wust dann auch mit anderen
> Dingen als mit 0 initialisierst. Dann kann niemand mehr Deinen Code
> nutzen.

Also nur "Anfänger" initialisieren Structs und Arrays im Setup. Ah ja, 
habe ich auch noch nicht gewusst.

Hast du überhaup schon mal im Projekt gearbeitet? Variablen können da 
genau so gut in einen Initialisierungslauf eingebunden werden. Das wird 
eben zum Schluss gejoint, zusammengefügt, wo ist das Problem? Oder ging 
es dir nur darum, das Wort "Anfänger" öffentlich plazieren zu können ;-)

Beitrag #5679780 wurde von einem Moderator gelöscht.
Beitrag #5679820 wurde von einem Moderator gelöscht.
Beitrag #5679858 wurde von einem Moderator gelöscht.
Beitrag #5679863 wurde von einem Moderator gelöscht.
Beitrag #5679869 wurde von einem Moderator gelöscht.
Beitrag #5679908 wurde von einem Moderator gelöscht.
Beitrag #5679973 wurde von einem Moderator gelöscht.
Beitrag #5680045 wurde von einem Moderator gelöscht.
Beitrag #5680063 wurde von einem Moderator gelöscht.
Beitrag #5680136 wurde von einem Moderator gelöscht.
Beitrag #5680148 wurde von einem Moderator gelöscht.
Beitrag #5680150 wurde von einem Moderator gelöscht.
von A. S. (Gast)


Lesenswert?

Glücklich ohne Grund schrieb:
> Also nur "Anfänger" initialisieren Structs und Arrays im Setup. Ah ja,

Nein.das sollte jeder tun aber nur für die Variablen, deren Startwert 
zur Linkzeit unbekannt ist sondern erst zur Laufzeit

> Hast du überhaup schon mal im Projekt gearbeitet?

Ja. Und auch in Projekten mit pre-ANSI-C Compiler, wo dein Vorgehen 
notwendig war. Oder Compiler für kleinste uC, deren Startup man selber 
schreiben musste das Nullen fehlte.

Aber der Pfeil geht Richtung standardkonformen Compiler. Und wenn eine 
Variable explizit mit 0 initialisiert wird, obwohl sie es auch implizit 
ist, dann kann das aus vielen Gründen OK sein.

Das aber vorsorglich und mit den von mir aufgezählten Klimmzügen zu 
machen, weil der Compiler einen Bug habe könnte oder weil der 
Programmierer den Unterschied zwischen statischen Variablen und Stack 
nicht kennt, belastet den Code.

Beitrag #5681388 wurde von einem Moderator gelöscht.
Beitrag #5681405 wurde von einem Moderator gelöscht.
Beitrag #5681437 wurde von einem Moderator gelöscht.
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.