Hallo!
Ich habe ein Problem beim Einlesen von SMS aus meinem TC35i Modem. Wo
die Daten herkommen ist eigentlich egal, das Problem liegt nämlich ganz
wo anderst.
Mein Code sieht folgendermaßen aus:
Hier wird das SMS ausgelesen (bzw mehrere) und in ein 721 Char breites
Array (sms_buffer[721])geschrieben. An der letzten Stelle steht '\0' um
den String abzuschließen - standard.
1
gsm_read_sms();
Die Daten stehen nun im Array. Ich habe ein Unterprogramm, welches die
Daten verarbeitet, in dieses Unterprogramm wird ein String übergeben
(sBase64_roh).
Also schreibe ich die Startadresse des Arrays auf *sBase64_roh und
übergebe diese.
In dem unten angeführten Beispiel wird sie nicht übergeben, sondern über
USART an den PC geschickt (zum Debuggen).
1
2
3
char*sBase64_roh;
4
charsms_buffer[721];
5
6
sBase64_roh=&sms_buffer[0];
7
8
Uart_Puts("AUSGABE DES ROH TEXTES: ");
9
Uart_Puts(sBase64_roh);
Die Situation ist folgende: Der Controller sendet die ganze Zeit
"AUSGABE DES ROH TEXTES: ". Mehr nicht, er scheint mit dem
"Uart_Puts(sBase64_roh);" offensichtlich nicht klarzukommen. Oder wo
könnte sonst der Hund begraben sein?
Danke für die Hilfe =)
Die oben von mir gewählte Ausdrucksweise ist nicht ganz richtig. Der
Pointer ist ja eine Adresse, aber ohne das * wird die Variable einfach
als numerischer Wert verarbeitet, nicht als Pointer.
Stimmts?
Totales Chaos. Du uebergibst einen Zeiger auf char, was man gemeinhin
"String" nennt. Und du rufst eine Funktion auf, die einen String
erwartet um ihn ueber die serielle Schnittstelle zu senden. Nur ist der
String nicht initialisiert, mit etwas Glueck ist also schon das erste
Zeichen 0 und du siehst - nix. Wenn du die Adresse lesbar verschicken
willst, wirst du sie nach Ascii formatieren muessen.
Du hast keinen Inhalt im sms_buffer[] (==sBase64_roh) in deinem
Codeschnippsel. Es ist, wenn wie gezeigt verwendet, mit dem gefüllt, was
zufällig im Stack steht.
Meist nichts druckbares. Oft auch mal eine 0, die das Ende des Strings
bedeutet.
Daher ist die Ausgabe die du angibst Plausibel.
Leute, die Casts sind in Ordnung, wenn auch unnötig.
char chArray[] ;
und
char *chPointer ;
sind Variablen mit äquivalenten Datenetypen. (Bis auf das Treatment von
Warnings)
>> Die 3(4?) Impliziten hier.
Da gibt es keinen implizite Casts.
Alle Datentypen passen perfekt zusammen.
> char[] zu char& zu char *
Den Cast gibt es in C gar nicht.
Und da an dieser Stelle char[] nichts anderes als eine
andere Schreibweise für char* ist, ist auch sofort ersichtlich,
dass es diesen cast, wenn es ihn gäbe, gar nicht braucht.
> sBase64_roh = &sms_buffer[0];
sms_buffer ist ein Array von char
sms_buffer[0] ist ein einzelnes Element aus diesem Array,
hat also den Datentyp char
&sms_buffer[0] Wendet man den Address Operator auf einen char an
erhält man selbstverständlich einen char*
sBase64_roh = &sms_buffer[0]; links vom = ist der Datentyp char *
rechts vom = ist der Datentyp char *
Also, warum soll da irgendetwas gecastet werden?
> und das ?:> char *> zu const char *
Das ist kein Cast.
In die umgekehrte Richtung wäre es einer.
Aber so rum passiert nichts, weil keine Notwendigkeit dazu besteht.
const ist die Zusicherung, nichts zu verändern.
Wenn dir dein Kumpel zusichert, in ein geliehenes Buch nichts
hinzuschreiben, kannst du ihm bedenkenlos deine wertvolle
Guthenberg-Bibel geben. Selbst wenn man in die prinzipiell etwas
hineinschreiben könnte (sie also nicht const ist), dein Kumpel behandelt
sie ja als nicht-beschreibbar (const)
Erst im umgekehrten Fall musst du dir Sorgen machen:
Deine Bibel ist const (also als nicht-beschreibbar anzusehen) und dein
Kumpel gibt dir bei der Übernahme nicht die Zusicherung, dieses const zu
respektieren.
Dann musst du dir überlegen, inwieweit du deinem Kumpel traust, und das
const für den Zeitraum des Ausleihens wegcastest.
> Der eine Implizite in>
1
>Uart_Puts(sms_buffer);
2
>
> hätte ausgereicht.
Wenn wir mal eine übliche Def. voraussetzen
void Uart_Puts( const char* string )
dann wird auch hier nichts implizit gecastet.
Die Initialisierung einer const Variablen mit einem Wert erfordert
keinen Cast, wenn der restlichen Datentypen übereinstimmt. Die Variable
legt sich stärkere Restriktionen auf, was mit ihr möglich ist. Das
tangiert aber nicht die Quelle des Wertes und erfordert auch keinerlei
Aktionen bei der Zuweisung.
Erst umgekehrt, wenn die Quelle über Restriktionen verfügt, die das Ziel
nicht gewillt ist einzuhalten (oder zumindest keine Zusage dafür
abgibt), sind Aktionen (wie zb ein Cast) notwendig.
@kbuchegg
Wirklich schön verständlich, deine Erklärungen. Danke dafür!
(Sollte auch mal gesagt werden)
Wäre interessant ob es dem TE auch weitergeholfen hat?
Loonix schrieb:
> Wäre interessant ob es dem TE auch weitergeholfen hat?
Dazu müsste man erst mal wissen, was er eigentlich machen will.
Will er den String an sich ausgeben, oder will er den numerischen Wert
der Adresse, an der der String gespeichert ist, wissen (wozu auch
immer).
Im ersten Fall, stimmt das schon so wie er das hat. Jedoch ist der
eigentliche String entweder nicht initialisiert oder es ist ganz einfach
ein Leerstring.
Im zweiten Fall, müsste er den numerischen Wert des Pointers erst mal
mit zb ltoa (wenn sizeof(long) == sizeof(void*)) oder sprintf selbst in
einen String umwandeln lassen, um den dann mittels Uart_Puts auszugeben.
>> char[] zu char& zu char *>> Den Cast gibt es in C gar nicht.
Achso. Dann ist die ANSI-C Spec falsch:
> If the unary * operator is applied to this> pointer explicitly, or implicitly as a result of subscripting, the> result is the pointed-to ( n -1)-dimensional array, which itself is> converted into a pointer if used as other than an lvalue.> The array-subscript> [] and member-access . and -> operators, the address & and> indirection * unary operators, and pointer casts may be used in the> creation an address constant, but the value of an object shall not be> accessed by use of these operators.
Ob die Konversation nun irgendwelche Instruktionen benötigt oder ohne
Zutun die Binärrepräsentation verwenden kann, ändert nichts daran, dass
es eine Wandlung (Cast) des qualifizierten Datentyps ist.
Nach Ansi-C sind die beiden qualifizierten Typen const char und char
nicht kompatibel.
Damit wird eine Wandlung (die aus Nichts ausser dem "Merken" des const
allein durch den Compiler besteht) in beide Richtungen nötig,
denn die Kompatibilitäts-Relation:
> For two qualified types to be compatible, both shall have the> identically qualified version of a compatible type; the order of type> qualifiers within a list of specifiers or qualifiers does not affect> the specified type.
ist offensichtlich symetrisch.
Tim Seidel schrieb:
>>> char[] zu char& zu char *>>>> Den Cast gibt es in C gar nicht.>> Achso. Dann ist die ANSI-C Spec falsch:
Wo kommt in den ANSI-C Spec der Datentyp char& (also eine Referenz) vor?
> Nach Ansi-C sind die beiden qualifizierten Typen const char und char> nicht kompatibel.
OK.
Trotzdem betreibst du hier Haarspalterei
(und wenn wir genau sind, haben wir von const char* und char*
gesprochen. Und diese beiden Datentypen SIND per Definition kompatibel.
Der C-Standard macht dafür extra eine Ausnahme :-)
Bei der Zuweisung eines int an einen long gibt es so gesehen dann auch
einen 'impliziten cast', der allerdings nicht wirklich irgend jemanden
auch nur im Geringsten interessiert. Und dort ändert sich unter
Umständen sogar das Bitmuster.
Tim Seidel schrieb:
>>> char[] zu char& zu char *>>>> Den Cast gibt es in C gar nicht.>> Achso. Dann ist die ANSI-C Spec falsch:>> If the unary * operator is applied to this>> pointer explicitly, or implicitly as a result of subscripting, the>> result is the pointed-to ( n -1)-dimensional array, which itself is>> converted into a pointer if used as other than an lvalue.>
Hmm. Der Punkt gilt ja wohl bei
sBase64_roh = &sms_buffer[0];
nicht. Denn hier wird kein unary * operator angewendet, weder explizit
noch implizit, denn der & operator und anwenden dieser Regel ...
>> The array-subscript>> [] and member-access . and -> operators, the address & and>> indirection * unary operators, and pointer casts may be used in the>> creation an address constant, but the value of an object shall not be>> accessed by use of these operators.
... verbietet das. Da ist ausdrücklich davon die Rede, dass & den Wert
nicht antatscht, dass es also bei der Auswertung von
&sms_buffer[0]
zu keinem impliziten unary * (Dereferenzierung) kommt. Statt dessen
steht da, dass eine "address constant" gebildet wird. Und eine "address
constant", vulgo Pointer, hat meines Wissens nicht den Datentyp
iregdnwas[] sondern irgendwas*
Karl heinz Buchegger schrieb:
> Tim Seidel schrieb:>>>> char[] zu char& zu char *>>>>>> Den Cast gibt es in C gar nicht.>>>> Achso. Dann ist die ANSI-C Spec falsch:>>> If the unary * operator is applied to this>>> pointer explicitly, or implicitly as a result of subscripting, the>>> result is the pointed-to ( n -1)-dimensional array, which itself is>>> converted into a pointer if used as other than an lvalue.>>>>> Hmm. Der Punkt gilt ja wohl bei> sBase64_roh = &sms_buffer[0];> nicht. Denn hier wird kein unary * operator angewendet, weder explizit> noch implizit, denn der & operator und anwenden dieser Regel ...
Doch, das wird es.
sBase64_roh = &sms_buffer[0]; evaluiert zu
sBase64_roh = &(*(sms_buffer+(0)))
>>>> The array-subscript>>> [] and member-access . and -> operators, the address & and>>> indirection * unary operators, and pointer casts may be used in the>>> creation an address constant, but the value of an object shall not be>>> accessed by use of these operators.>> ... verbietet das. Da ist ausdrücklich davon die Rede, dass & den Wert> nicht antatscht, dass es also bei der Auswertung von
Du missverstehst den Satz.
Was dort beschrieben wird ist z.B. die folgende Situation (absichtlich
alles dabei):
1
chararray[4]={1,2,3,4};
2
u32val=*(int*)&array[0];
Hier wird der Typ des Pointer gecastet. Der Wert jedoch wird nicht
angetatstet (weder gelesen noch geschrieben)
val ist nach dem Satz oben das int an der Stelle von array (je nach
endianess) und nicht (das ist die zentrale Aussage, neben der
Seitenbemerkung, dass es sich bei subscriptions des ersten Quotes um
Casts handelt) dass val = (int) 1 ist. (bei dem der Wert angefasst und
erweiter worden wäre.
> &sms_buffer[0]>> zu keinem impliziten unary * (Dereferenzierung) kommt. Statt dessen> steht da, dass eine "address constant" gebildet wird. Und eine "address> constant", vulgo Pointer, hat meines Wissens nicht den Datentyp> iregdnwas[] sondern irgendwas*>>> may be used in the>>> creation an address constant
Da steht nicht, wie du hier behaupten willst. Schlüsselworte sind hier
"may" und in vorderster front "in the creation". Genauer: a) Es muss
nicht b) und es muss nicht in einem Schritt erledigt sein
Also kann und muss (um OBdA zu arbeiten) angenommen werden, dass jeder
Schritt zur Adressenbildung auch durchgeführt wird.
PS: Das mit dem Haarespalten fing m.E. früher an. Ich lass mich ungern
mit falschen Aussagen korrigieren. Insbesondere dann nicht, wenn diese
falschen Aussagen von Accounts kommen, die eine besondere Verpflichtung
zur Genauigkeit und gutem Umgangston haben.
Und das für die simple Aussage, dass die Typzuweisungen passen ... naja
Tim Seidel schrieb:
> Und das für die simple Aussage, dass die Typzuweisungen passen ... naja
Genau das ist der springende Punkt
Wiellst du in Zukunft jede Zuweisung ala
long i;
i = 5;
mit 'die impliziten Casts sind ok' kommentieren?
Dein Aufbringen der Thematik Casting trägt in dieser Fragestellung
nichts bei.
Dann siehst du, ob zumindest der Kram funzt (sollte). Ab wo beginnst du
dein array zu füllen, ab [0] oder [1] ?
Falls erst bei [1], dann könnte in [0] eine 0 stehen, das wäre das Ende
deines strings :-)
Noch ein Tipp: (s)printf liefert dir die Zahl der Zeichen zurück, damit
kann man schöne Sachen machen wie:
1
charstring[1024];
2
char*pString;
3
4
pString=string;
5
6
pString+=sprintf(pString,"Hallo ");
7
pString+=sprintf(pString,"Welt");
8
9
printf(string);
Anmerkung: Ev. die n-variante vom sprintf (snprintf) verwenden, auf die
Gefahr eines Überlaufes hin.
VG,
/th.
Moin zusammen,
um die Sache mal von einer anderen Richtung anzugehen: Es ist nicht
zufällig ein AVR-Prozessor und das leidige Problem mit Strings im RAM
oder im Flash?
Denn die umfängliche Diskussion über cast verdeckt meiner Meinung nach,
dass das Ausgangsprogramm eigentlich funktionieren müsste...
Gruß
Jens
Ralf schrieb:
> char *sBase64_roh;> char sms_buffer[721];>> sBase64_roh = &sms_buffer[0];>> Uart_Puts("AUSGABE DES ROH TEXTES: ");> Uart_Puts(sBase64_roh);
Kann es nicht sein, dass die Zeile
> Uart_Puts(sBase64_roh);
einfach gar nichts bewirkt, also keine Ausgabe erzeugt, weil sms_buffer
keine sinnvoll ausgebbaren Zeichen enthält ?
Und Du daher nur die Ausgabe "AUSGABE DES ROH TEXTES: " siehst ?
Also, zum Test:
sms_buffer mit einem String initialisieren und dann wird Uart_Puts()
auch diesen anzeigen. Dann gehts weiter.
Karl heinz Buchegger schrieb:
> Tim Seidel schrieb:>>> Und das für die simple Aussage, dass die Typzuweisungen passen ... naja>> Genau das ist der springende Punkt> Wiellst du in Zukunft jede Zuweisung ala>> long i;> i = 5;>> mit 'die impliziten Casts sind ok' kommentieren?> Dein Aufbringen der Thematik Casting trägt in dieser Fragestellung> nichts bei.
Zumindest dann, wenn wie geschehen behauptet wird, dass die Zuweisung
nicht in Ordnung ist.