Forum: Mikrocontroller und Digitale Elektronik char String Null im Array verhindern


von Array (Gast)


Lesenswert?

Hallo,


ich möchte eine Reihe AT Befehle in Arrays ablegen.

Wenn ich einfach

char Befehl[] = {"AT+"};

schreibe, erhalte ich im Array
'A','T','+','NULL'

also 4 Bytes.

Die "NULL" stört, weil ja der eigentliche Befehl noch nachfolgend 
geschickt wird.
Wie kann ich also mit der geringsten Schreibarbeit verhindern, dass die 
'NULL' am Ende mit im Array abgelegt wird?

Funktioniert dieses Vorhaben, wenn ich einfach:
char Befehl[3] = {"AT+"};

definiere und somit den Platz im Array auf meine drei Wunsch-Bytes 
reduziere?

von Peter II (Gast)


Lesenswert?

Array schrieb:
> Die "NULL" stört, weil ja der eigentliche Befehl noch nachfolgend
> geschickt wird.

dann stört sie aber nicht, denn sie wird nicht versendet. Sonst musst du 
dir ja wieder etwas einfallen lassen, damit du die länge der Daten 
kennst.

von Array (Gast)


Lesenswert?

nun, ich lege meine Arrays mit vordefinierten Kommandos ja alle in den 
Speicher ab.

Erstens möchte ich nicht, dass bei jedem Befehl in jedem Array diese 
NULL mit gespeichert wird.
Zweitens möchte ich nicht, dass sie versendet wird, weil mein Funkmodul 
dies ja wieder nicht verstehen würde.
Also möchte ich sie gar nicht erst irgendwo mit ablegen.

von Thomas E. (thomase)


Lesenswert?

Array schrieb:
> Funktioniert dieses Vorhaben, wenn ich einfach:
> char Befehl[3] = {"AT+"};
>
> definiere und somit den Platz im Array auf meine drei Wunsch-Bytes
> reduziere?

Nein, dann wird die 0 dahinter geschrieben und zerstört das folgende 
Byte. Außerdem gibt es Mecker vom Compiler.

Die 0 ist die Terminierung eines Strings in C. Wenn du das verhindern 
willst, mußt du dir eine andere Programmiersprache suchen.

von Thomas E. (thomase)


Lesenswert?

Array schrieb:
> Zweitens möchte ich nicht, dass sie versendet wird, weil mein Funkmodul
> dies ja wieder nicht verstehen würde.

Das tut man gewöhnlich auch nicht.

von Peter II (Gast)


Lesenswert?

Thomas E. schrieb:
> Nein, dann wird die 0 dahinter geschrieben und zerstört das folgende
> Byte.
nein

> Außerdem gibt es Mecker vom Compiler.
nein

von Peter II (Gast)


Lesenswert?

Array schrieb:
> Zweitens möchte ich nicht, dass sie versendet wird, weil mein Funkmodul
> dies ja wieder nicht verstehen würde.

sie wird doch gar nicht gesendet. Bei String-Funktionen werden alle 
Zeichen bis zur NULL verarbeitet aber nicht die NULL selber.

Wenn du printf verwendest, wird auch keine NULL ausgegeben, obwohl sie 
enthalten ist.

von Pandur S. (jetztnicht)


Lesenswert?

Allenfalls muss man mit einer eigenen String Klasse arbeiten, die ohne 
Null arbeitet.

von Array (Gast)


Lesenswert?

Ja, die NULL terminiert einen String.
Mein Funkmodul mit AT-Kommandos will aber keine NULL haben, sondern 
genau "AT+KOMMANDO\r"

Der Befehl "AT+KOMMANDO\NULL\r" würde ja schon wieder nicht verstanden 
werden.

von Michael B. (laberkopp)


Lesenswert?

Array schrieb:
> Erstens möchte ich nicht, dass bei jedem Befehl in jedem Array diese
> NULL mit gespeichert wird.

Das ist aber bei Strings in C so üblich.

> Zweitens möchte ich nicht, dass sie versendet wird, weil mein Funkmodul
> dies ja wieder nicht verstehen würde.

Warum sollte die NUL mitversendet werden ?

Das passiert doch nur, wenn du etwas falsch programmierst.

Ein

fputs(Befehl,f)

ein

write(f,Befehl,strlen(Befehl));

sendet auch keine NUL mit

nur ein

fwrite(f,sizeof(Befehl),1,Befehl);

würde sie mitsenden, dann hat du eben falsches programmiert.

> Funktioniert dieses Vorhaben, wenn ich einfach:
> char Befehl[3] = {"AT+"};

Nein, bitte lese ein Grundlagenbuch zu C.

von Peter II (Gast)


Lesenswert?

Array schrieb:
> Der Befehl "AT+KOMMANDO\NULL\r" würde ja schon wieder nicht verstanden
> werden.

die null wird nicht gesendet!

Wie sendest du denn deine Daten?

von Dietrich L. (dietrichl)


Lesenswert?

Array schrieb:
> Erstens möchte ich nicht, dass bei jedem Befehl in jedem Array diese
> NULL mit gespeichert wird.
> Zweitens möchte ich nicht, dass sie versendet wird, weil mein Funkmodul
> dies ja wieder nicht verstehen würde.
> Also möchte ich sie gar nicht erst irgendwo mit ablegen.

Ein String endet immer mit NULL, gleichzeitig dient diese NULL als 
Längenangabe des Strings. Die C-Stringfunktionen "leben" davon.

Wenn Du also zum Versenden Stringfunktionen verwendet ist das so genau 
richtig, und die NULL wird nicht mit versendet.

Wenn Du die NULL nicht haben willst: wie erkennst Du dann die Länge des 
AT-Befehls? Oder verwendest Du (zufällig) nur 3-Byte-Befehle?

von Array (Gast)


Lesenswert?

Wird die NULL bei einer "normalen" Uart-Verbindung tatsächlich nicht 
gesendet, auch dann nicht wenn sie Bestandteil des Stringarrays ist, 
welches man an die Funktion übergibt?

von Peter II (Gast)


Lesenswert?

Michael B. schrieb:
>> Funktioniert dieses Vorhaben, wenn ich einfach:
>> char Befehl[3] = {"AT+"};
>
> Nein, bitte lese ein Grundlagenbuch zu C.

oder du.

Das ist schon so ok.

von Peter II (Gast)


Lesenswert?

Array schrieb:
> Wird die NULL bei einer "normalen" Uart-Verbindung tatsächlich nicht
> gesendet, auch dann nicht wenn sie Bestandteil des Stringarrays ist,
> welches man an die Funktion übergibt?

wenn man die richtigen Funktionen verwendet: ja

von Dr. Sommer (Gast)


Lesenswert?

Kleine Pingeligkeit: NULL ist ein Makro für Null-*Pointer*. Die 0 im 
letzten char ist eine "echte" 0, d.h. der Integer-Wert 0 (kein 
Pointer!). Daher ist es etwas ungeschickt, hier NULL zu schreiben. Würde 
man im Code hier explizit NULL verwenden, können sich u.U. auch Probleme 
ergeben.

von Justus S. (jussa)


Lesenswert?

Array schrieb:
> Wird die NULL bei einer "normalen" Uart-Verbindung tatsächlich nicht
> gesendet, auch dann nicht wenn sie Bestandteil des Stringarrays ist,
> welches man an die Funktion übergibt?

da niemand hier wissen kann, welche Funktionen du zum Senden benutzt, 
ist eine sinnvolle Antwort eigentlich nicht möglich...

von Peter D. (peda)


Lesenswert?

Array schrieb:
> Funktioniert dieses Vorhaben, wenn ich einfach:
> char Befehl[3] = {"AT+"};

Ja, das ist erlaubt.
Bloß wie soll dann die Senderoutine hellsehen, daß es sie 3 Bytes senden 
soll?
Die '/0' als Endekennzeichen hat man sich nämlich nicht aus Jux und 
Dollerei ausgedacht.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Array schrieb:
> char Befehl[] = {"AT+"};

Das ist ziemlich unsinnig. Ein Array, welches kein weiteres Zeichen 
aufnehmen kann, und (vermutlich) auch nicht modifiziert werden soll,
braucht überhaupt nicht im RAM zu liegen, sondern belegt nur Platz.

Welchen µC nutzt Du? Zeig doch mal die Verwendung von Befehl[]. Das kann 
man bestimmt auch anders schreiben...

Array schrieb:
> Funktioniert dieses Vorhaben, wenn ich einfach:
> char Befehl[3] = {"AT+"};

Ja, das funktioniert und es gibt auch keinen Mecker vom Compiler, weil 
das in C ausdrücklich so definiert ist, dass in diesem speziellen Fall 
(Größe des Arrays == Länge des Strings) das Speichern des NUL-Bytes (Ja, 
es heisst NUL mit einem L bzw. '\0' und nicht NULL) unterbleibt.

Aber dann kommt es stark darauf an, was Du mit Befehl[] macht. strcpy() 
und Co. sind dann jedenfalls nicht mehr anwendbar. Befehl[] ist dann nur 
noch ein Array und kein C-String mehr.

Also: Zeig bitte die Verwendung. Darauf kommt es an.

von Rolf Magnus (Gast)


Lesenswert?

Array schrieb:
> Hallo,
>
> ich möchte eine Reihe AT Befehle in Arrays ablegen.
>
> Wenn ich einfach
>
> char Befehl[] = {"AT+"};
>
> schreibe, erhalte ich im Array
> 'A','T','+','NULL'
>
> also 4 Bytes.

nicht 'NULL', sondern '\0'. Mit NULL hat das überhaupt nichts zu tun.

> Funktioniert dieses Vorhaben, wenn ich einfach:
> char Befehl[3] = {"AT+"};
>
> definiere und somit den Platz im Array auf meine drei Wunsch-Bytes
> reduziere?

Ja, das geht in C (nicht allerdings in C++). Du kannst dann aber keine 
Standard-String-Funktionen mehr nutzen, weil die auf die 0 am Ende 
angewiesen sind, um die Länge zu ermitteln. Du musst also alles mit 
eigenen Funktionen machen und dir die Länge irgendwie separat merken.

Array schrieb:
> Ja, die NULL terminiert einen String.

Ja, genau. Das heißt, es wird alles vor der 0 als Teil des 
Stringinhalts verarbeitet, die 0 aber nicht. Sie ist nur der Marker, 
dass der eigentliche Inhalt bis ein Zeichen vor der 0 geht.

Array schrieb:
> Wird die NULL bei einer "normalen" Uart-Verbindung tatsächlich nicht
> gesendet, auch dann nicht wenn sie Bestandteil des Stringarrays ist,
> welches man an die Funktion übergibt?

Das hängt von deiner Funktion ab, aber wenn das eine ist, die für 
Stringhandling ausgelegt ist, dann schickt das \0 nicht mit. Wenn nicht, 
musst du aber eh irgendwo explizit die Länge des Arrays angeben. Dann 
kannst du auch einfach die Länge ohne das \0 angeben.
Dafür ist das \0 ja da: Damit die Stringfunktionen wissen, wo der String 
zu ende ist. Lässt du das weg, können sie die Länge nicht mehr daraus 
ermitteln.

Michael B. schrieb:
>> Funktioniert dieses Vorhaben, wenn ich einfach:
>> char Befehl[3] = {"AT+"};
>
> Nein, bitte lese ein Grundlagenbuch zu C.

Wer so rumtönt, sollte sich erstmal selbst mit den Grundlagen 
beschäftigen.
1
char Befehl[3] = {"AT+"};
macht genau das, was er sich vorstellt. Es ergibt einen String ohne das 
abschließende \0.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Oh D. schrieb:
> Allenfalls muss man mit einer eigenen String Klasse arbeiten, die ohne
> Null arbeitet.

Und welchen Vorteil hätte die? Das Ende bzw. die Länge von Strings 
müsste sie sich auch irgendwie merken. Speicherplatz spart das nicht.

von Array (Gast)


Lesenswert?

so würde ich das aufbauen:
char AT_Command[]={"AT+"};
char AT_Restart[]={"RST"};
... weitere AT-Befehle.


Das eigentliche Modul möchte "AT+RST" empfangen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Array schrieb:
> Das eigentliche Modul möchte "AT+RST" empfangen.

Dann zeig endlich den Aufruf, wie Du das dem Modul sendest! Denn damit 
ist es noch lange nicht getan. Da fehlt mindestens ein '\r'.

von Pandur S. (jetztnicht)


Lesenswert?

> Und welchen Vorteil hätte die? Das Ende bzw. die Länge von Strings
müsste sie sich auch irgendwie merken. Speicherplatz spart das nicht.

Eine eigene Stringklasse mit der Laenge separat duerfte dann die Null 
als gueltigen Character enthalten, auch mehrfach.
Ja, manche moegen das Missbrauch nennen und auf andere Strukturen 
verweisen. Dann nennt man's eben anders.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Oh D. schrieb:
> Eine eigene Stringklasse mit der Laenge separat duerfte dann die Null
> als gueltigen Character enthalten, auch mehrfach.

Dürfte sie, aber ... wozu braucht man das?

Wenn man es einfach Bytearray nennt ... ist's weder was neues noch was 
verwirrendes.

Um aber einem Modem AT-Kommandos zu senden, ist die Idee reichlich 
bizarr, hier auf Strings zu verzichten.

von Dirk B. (dirkb2)


Lesenswert?

Array schrieb:
> so würde ich das aufbauen:
> char AT_Command[]={"AT+"};
> char AT_Restart[]={"RST"};
> ... weitere AT-Befehle.
>
>
> Das eigentliche Modul möchte "AT+RST" empfangen.

Du kannst da sogar zwei Aufrufe zum Senden machen. Du musst nicht erst 
einen neuen String zusammen basteln.

von Rampensau (Gast)


Lesenswert?

Peter II schrieb:
> Wie sendest du denn deine Daten?

Justus S. schrieb:
> da niemand hier wissen kann, welche Funktionen du zum Senden benutzt,
> ist eine sinnvolle Antwort eigentlich nicht möglich...

Frank M. schrieb:
> Also: Zeig bitte die Verwendung. Darauf kommt es an.

Frank M. schrieb:
> Dann zeig endlich den Aufruf, wie Du das dem Modul sendest!

Bis dahin ist eine weitere Diskussion wohl überflüssig ...

von Amateur (Gast)


Lesenswert?

@A-rray
Die str-Befehle basieren auf 0-Terminierten Zeichenketten. Das ist 
sozusagen "eingebaut".
Der Befehl strcat () z.B., kopiert alles EXCLUSIVE" der angehängten 
Null. Hängt aber die Null, zur weiteren Verwendung, hinten an.

Der Glaube, das Weglassen der angehängten Null, würde Platz sparen, ist 
ebenfalls Unsinn.
"Zeichenkette Eins" und "Zeichenkette Sieben" benötigen für jede Ausgabe 
oder Bearbeitung eine Längenkonstante. Also die Konstanten 17 und 19. 
Oder einen Algorithmus, der alles bis zur angehängten Null ausgibt.
Ersparnis = Null; Fehlerwahrscheinlichkeit maximal.

Darüber hinaus haust Du Dir die Finger wund, wenn Du
statt: "Zeichenkette Eins"
'Z','e','i','c','h','e','n','k','e','t','t','e',' ','E','i','n','s'; als 
normal ansiehst. Und die Länge überall mit mitschleppst.

Also, was Du vorhast geht, ist aber schlicht und einfach Krampf.

Und wie auch meine Vorgänger bereits gefragt haben: Was soll das Ganze?

von A. S. (Gast)


Lesenswert?

Array schrieb:
> so würde ich das aufbauen:
> char AT_Command[]={"AT+"};
> char AT_Restart[]={"RST"};
> ... weitere AT-Befehle.
>
>
> Das eigentliche Modul möchte "AT+RST" empfangen.

mmm., vielleicht lieber so:
1
const char * const AT_Command="AT+";
2
const char * const AT_Restart="RST";
3
4
void sendCommand(const char *p1, const char *p2, const char *p3)
5
{
6
   if(p1) {while(*p1) {SendByte(*p1++);}}
7
   if(p2) {while(*p2) {SendByte(*p2++);}}
8
   if(p3) {while(*p3) {SendByte(*p3++);}}
9
}
10
11
... 
12
    sendCommand(AT_Command, AT_Restart, 0);
kein schöner Code, sicher voller Schreibfehler, aber ein Beispiel für 
0-Terminierung und damit Du beschreiben kannst, was Du eigentlich 
möchtest.

Die je 2 const zeigen übrigens (wie von anderen angemerkt) dass hier 
garkein RAM belegt werden braucht.

von Array (Gast)


Lesenswert?

...ok, danke für die vielen Antworten. Werde also erstmal die 
vorgegebene \0 verwenden. Macht viele gegebene Funktionen besser 
verwendbar.


Eine Frage noch:

char Array[]={"x"}
Wenn ich die Funktion sizeof(Array) verwende, dann müsste sie mir als 
Ergebnis "2" zurückgeben, richtig?

von nicht“Gast“ (Gast)


Lesenswert?

Das ist richtig.

Für strings gibt's aber strlen. Das gibt korrekt 1 zurück

von Dirk B. (dirkb2)


Lesenswert?

Array schrieb:
> char Array[]={"x"}
> Wenn ich die Funktion sizeof(Array) verwende, dann müsste sie mir als
> Ergebnis "2" zurückgeben, richtig?

Nein, sie gibt 2 (ohne ") zurück.

von Achim (Gast)


Lesenswert?

Array schrieb:
> Wenn ich die Funktion sizeof(Array) verwende, dann müsste sie mir als
> Ergebnis "2" zurückgeben, richtig?

Wobei es Du sizeof oder strlen meist nicht brauchst. Bei Strings oder 
Streams ist ein for i oder ein memcpy selten sinnvoll.

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.