Forum: Mikrocontroller und Digitale Elektronik PIC XC8 "warning: (359) illegal conversion between pointer types"


von PICianer (Gast)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

PICianer schrieb:
> void LCD_Text(char y, char x, char *text);

teste mal mit

void LCD_Text(char y, char x, const char *text);

von Karl H. (kbuchegg)


Lesenswert?

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
von PICianer (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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
von PICianer (Gast)


Lesenswert?

@kbuchegg: Jetzt sehe ich das dein Post noch bearbeitet wurde. Danke für 
die ausführliche Erklärung.

von Karl H. (kbuchegg)


Lesenswert?

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
von Yalu X. (yalu) (Moderator)


Lesenswert?

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
Noch kein Account? Hier anmelden.