Ich habe mir eine Funktion geschrieben um ein LCD mit meinem PIC18F4550 anzusteuern. Die Funktion um Text auszugeben sieht so aus: void LCD_Text(char y, char x, char *text); Wenn ich einen String übergebe funktioniert alles Problemlos, wenn ich hingegen so mach LCD_Text(1,1,"Hallo Welt"); gibt der Compiler die oben genannte Warnung aus, der Text wird aber trotzdem richtig angezeigt. Gibt es eine Möglichkeit diese Warnung wegzubekommen ohne eine eigene Funktion mit const char *text als Übergabeparameter zu schreiben?
PICianer schrieb: > void LCD_Text(char y, char x, char *text); teste mal mit void LCD_Text(char y, char x, const char *text);
PICianer schrieb: > Gibt es eine Möglichkeit diese Warnung wegzubekommen ohne eine eigene > Funktion mit const char *text als Übergabeparameter zu schreiben? Was stört dich daran. const char* wäre prinzipiell sogar die richtigere Variante.
:
Bearbeitet durch User
Karl Heinz schrieb: > Was stört dich daran. Ich dachte, dass ich dann zwei Funktionen hatte, eine für char die andere für const char. Jetzt sehe ich aber, dass ich der Funktion die const cahr* erwartet ohne Warnung ein char* übergeben kann. Wieso geht das und umgekehrt nicht?
PICianer schrieb: > Karl Heinz schrieb: >> Was stört dich daran. > Ich dachte, dass ich dann zwei Funktionen hatte, eine für char die > andere für const char. Jetzt sehe ich aber, dass ich der Funktion die > const cahr* erwartet ohne Warnung ein char* übergeben kann. Wieso geht > das und umgekehrt nicht? Das const bedeutet an dieser Stelle ja nicht, dass du nur konstante Texte ausgeben kannst. Ein const in der Argumentliste bedeutet an dieser Stelle, dass die Funktion die Zusicherung an den Aufrufer gibt "Ich werde nicht versuchen, den Text den du mir gibst zu verändern". Für einen Aufruf ala
1 | LCD_Text( 1, 1, "Hallo" ); |
wäre das eine notwendige Voraussetzung, weil "Hallo" als Stringliteral ja nicht per Programm verändert werden darf. Daher sollte die Funktion auch genau diese Zusicherung machen. Für einen Aufruf ala
1 | char str[] = "Hallo"; |
2 | LCD_Text( 1, 1, str ); |
ist die Zusicherung zwar nicht notwendig, es ist aber trotzdem für den
Aufrufer gut zu wissen, dass nach Aufruf der Funktion in str nach wie
vor der String "Hallo" unverändert drinnen stehen wird.
So 'in a nutshell'
> Wieso geht das und umgekehrt nicht?
Weil es Dinge gibt, die von Haus aus const sind und das auch bleiben
müssen. Wenn eine Funktion sich so verhält, dass sie das warauf der
Pointer zeigt nicht verändert, dann ist das gewährleistet.
Gibst du der Funktion umgekehrt aber etwas, das die Funktion verändern
könnte, wenn sie wollte, die Funktion macht aber genau das nicht (das
Verändern), dann passiert weiter nichts schlimmes.
:
Bearbeitet durch User
@kbuchegg: Jetzt sehe ich das dein Post noch bearbeitet wurde. Danke für die ausführliche Erklärung.
Interessant ist in diesem Zusammenhang noch, dass eine derartige Verletzung eigentlich ein Fehler ist. Warum ist das dann in deinem Fall nur eine Warnung? Die Antwort darauf lautet: Weil genau für diesen einen Fall eines char Pointers eine Ausnahme in den C-Standard eingebaut wurde. const war nicht immer in der Sprachdefinition drinnen und ist erst später hinzugekommen. Das 'Problem' wäre gewesen, dass da draussen Unmengen von altem C Code existiert hätte, die damit automatisch fehlerhaft gewesen wären. Und davor schreckt man bei einer Spracherweiterung im Komitee immer zurück: Was bisher gültiger C Code war, soll auch in der nächsten Standarddefinition gültiger C Code sein. Also Das hier ...
1 | void foo( int* i ) |
2 | {
|
3 | printf( "%d\n", *i ); |
4 | }
|
5 | |
6 | int main() |
7 | {
|
8 | const int i = 5; |
9 | |
10 | foo( &i ); |
11 | }
|
... ist ein Fehler. Während das hier
1 | void foo( char* s ) |
2 | {
|
3 | printf( "%s\n", s ); |
4 | }
|
5 | |
6 | int main() |
7 | {
|
8 | const char* c = "hallo"; |
9 | |
10 | foo( &c ); |
11 | }
|
KEIN Fehler ist. Der Unterschied besteht einzig und alleine darin, dass es sich in dem einen Fall um einen int-Pointer handelt, während man es im anderen Fall mit einem char-Pointer zu tun hat, für den explizit eine Ausnahme im C-Standard gemacht wird, damit alter Code, der vor Einführung von const in die Sprache geschrieben wurde ...
1 | void foo( char* s ) |
2 | {
|
3 | printf( "%s\n", s ); |
4 | }
|
5 | |
6 | int main() |
7 | {
|
8 | foo( "Hallo" ); |
9 | }
|
... nach wir vor gültiger Code bleibt. Was deinen Compiler aber (dankenswerterweise) nicht daran hindert, eine Warnung dafür zu generieren.
:
Bearbeitet durch User
Bei den drei Beispielen von Karl Heinz (beim zweiten sollte wohl (foo(c) statt foo(&c) stehen) muss man zwischen C und C++ unterscheiden: In C sind alle drei Beispiele korrekt, wenngleich der Compiler in den ersten beiden Fällen evtl. (zurecht) eine Warnung ausgibt, weil die übergebenen Zeigertypen nicht komatibel sind. Das dritte Beispiel liefert keine Warnung, da in C Stringliterale vom Typ char* (und nicht etwa const char*) sind. Trotzdem sollte man nicht versuchen, ein Stringliteral direkt oder indirekt zu überschreiben, denn das führt zu undefiniertem Verhalten. In C++ hingegen sind die ersten beiden Beispiele fehlerhaft, da das const hier nicht implizit weggecastet wird. Da in C++ (anders als in C) Stringliterale vom Typ const char* sind, wäre normalerweise auch das dritte Beispiel fehlerhaft. Hier macht der C++-Standard allerdings eine Ausnahme und lässt die implizite Konvertierung eines const char* in ein char* derzeit noch zu (deprecated), der Compiler sollte aber eine Warnung ausgeben. Diese Ausnahme gilt jedoch nur für Stringliterale, nicht für beliebige const-char-Zeiger (wie etwa im zweiten Beispiel).
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.