Forum: Compiler & IDEs GCC: Compiler-Fehlermeldung bei Übergabe an Pointer


von Mario M. (Gast)


Lesenswert?

Hallihallo,
bin gerade an einem Programm. Hier die relevanten schnipsel:

1
void function(uint8_t *text)
2
{
3
   
4
}
5
6
int main(void)
7
{
8
   function("Hallo");
9
}

Der Compiler motzt beim Funktionsaufruf mit folgender Meldung:
"warning: pointer targets in passing argument 1 of `function` differ in 
signedness"

Was ist da los? Beim zweiten Durchlauf des Compilers verschwindet die 
Warnung. Compiliert wird mit WinAVR im AVRstudio

Gruss
Mario

von Oliver (Gast)


Lesenswert?

Deine Funktion erwartet einen u(nsigned)int_8*, für "Hello" wird aber 
ein char* erzeugt, der normalerweise signed ist. Also warnt der 
Compiler.

Wenn der Funktionsparameter ein pointer auf einen char sein soll, warum 
nimmst du dann dafür keinen char*?

>Beim zweiten Durchlauf des Compilers verschwindet die
>Warnung.

Das sollte (und kann) eigentlich nicht sein.

Oliver

von CHAR (Gast)


Lesenswert?

Schau dir mal die Wertebereiche von uint8_t (unsigned int 8 bit) und 
int8_t (signed int 8 bit).

Deine Funktion möchte unsigned Daten aber du übergibst signed Daten 
(Strings sind bei gcc signed).

von Sven P. (Gast)


Lesenswert?

Drei Möglichkeiten:

Erstens:
1
/* Parameter als char vereinbaren */
2
void function(char *text) {
3
   
4
}
5
6
int main(void) {
7
   function("Hallo");
8
}


Zweitens:
1
void function(uint8_t *text) {
2
   
3
}
4
5
int main(void) {
6
   /* Zeiger casten */
7
   function((uint8_t *) "Hallo");
8
}


Drittens:
Quelltext beibehalten und dem Compiler ein -munsigned-char mit geben.


Dann:
>Beim zweiten Durchlauf des Compilers verschwindet die
>Warnung.

Die Warnung verschwindet net, aber der Quelltext wird beim zweiten 
Durchlauf nicht mehr compiliert...dafür sorgt das Makefile. Mach mal 
einen Durchlauf (erwartungsgemäß kommt dein Fehler), dann mach noch 
einen (kein Fehler mehr), dann setz das Datum der letzten Änderung auf 
aktuell (einmal Speichern bzw. "touch <datei>.c"), dann kompilier 
nochmal...dann sollte dein Fehler wieder da sein.

von Mario M. (Gast)


Lesenswert?

Huiii, Danke vielmals für die Erläuterungen! Jetzt klappt es. Und doch: 
die Warnung verschwindet nach dem zweiten mal compilieren und das Proggi 
tut was es soll.
Was meinst du mit deiner dritten Möglichkeit? Bzw. wie machen?

Herzlichen Gruss und vielen Dank

Mario

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Sven Pauli wrote:

> Drittens:
> Quelltext beibehalten und dem Compiler ein -munsigned-char mit geben.

Falsch.

Ein portables Programm muss die Datentypen "char", "signed char"
und "unsigned char" als drei voneinander verschiedene, nicht direkt
zuweisungkompatible Datentypen behandeln -- egal, ob "char" nun in
der konkreten Implementierung vorzeichenbehaftet ist oder nicht.

Das bedeutet, dass alle Übergänge zwischen diesen Typen einen
Typecast brauchen, damit sichergestellt ist, wie die Vorzeichenhaftig-
keit zu übertragen ist.

In der Praxis dürfte es am sinnvollsten sein, "char" ausschließlich
für darstellbare Zeichen zu benutzen, mit deinen keinerlei Mathematik
in irgendeiner Form veranstaltet wird, und "signed char" (alias int8_t)
bzw. "unsigned char" (alias uint8_t) für Aufgaben, bei denen es um
kleine Ganzzahlen geht.

Man hat dann typischerweise genau an einer einzigen Stellen einen
Typecast, wenn es um den Typ "char" geht, das ist die Stelle, an der
die interne Eigenschaft als druckbares Zeichen auf externe Hardware
übergeben wird, also bspw. bei der Zuweisung an das UDR der UART.

von Sven P. (Gast)


Lesenswert?

Jörg Wunsch wrote:
> Sven Pauli wrote:
>
>> Drittens:
>> Quelltext beibehalten und dem Compiler ein -munsigned-char mit geben.
>
> Falsch.
Jo, falsch. Es muss -funsigned-char (-f!) heißen.


> Ein portables Programm muss die Datentypen "char", "signed char"
> und "unsigned char" als drei voneinander verschiedene, nicht direkt
> zuweisungkompatible Datentypen behandeln -- egal, ob "char" nun in
> der konkreten Implementierung vorzeichenbehaftet ist oder nicht.
Jein. Die Bibel sagt, Char ist entweder_ gleich signed char _oder 
gleich unsigned char, das ist maschinenabhängig. Wenns um druckbare 
Zeichen geht, isses aber grundsätzlich unsigned. (K&R-Programmieren in 
C, 2. Ausg von 1990, Seite 36).

> In der Praxis dürfte es am sinnvollsten sein, "char" ausschließlich
> für darstellbare Zeichen zu benutzen, mit deinen keinerlei Mathematik
> in irgendeiner Form veranstaltet wird, und "signed char" (alias int8_t)
> bzw. "unsigned char" (alias uint8_t) für Aufgaben, bei denen es um
> kleine Ganzzahlen geht.
In der Praxis ists am sichersten, für Rechnerei <stdint.h> zu verwenden 
und char immer mit unsigned zu vereinbaren bzw. das dem Compiler schon 
klar zu machen.


@Mario
>die Warnung verschwindet nach dem zweiten mal compilieren und das Proggi
>tut was es soll.
Wie gesagt, beim zweiten Mal compilieren wird dein Quelltext garnicht 
mehr compiliert. Der Computer merkt, dass sich seit dem letzten 
Durchlauf am Quelltext nix verändert hat (Datum der letzten Änderung der 
Datei) und überspringt ihn einfach.

von Andreas K. (a-k)


Lesenswert?

Sven Pauli wrote:

> Jein. Die Bibel sagt, Char ist entweder gleich signed char _oder_
> gleich unsigned char, das ist maschinenabhängig.

Wenn du C++ mit ins Boot nimmst, dann sind es doch wieder 3. Zwar ist 
auch da "char" technisch identisch mit einem der beiden anderen Typen 
und anfangs war das wie in C. Aber weil man damit sehr schlechte 
Erfahrung gemacht hat, sind das in C++ mittlerweile 3 formell 
inkompatible Typen. Ein "char *" ist auch dann zu einem "signed char *" 
imkompatibel, wenn beide technisch identisch sind.

Zwar gilt dies nur für C++, es ist aber zu empfehlen, sich auch bei C 
einigermassen dran zu halten.

> und char immer mit unsigned zu vereinbaren bzw. das dem Compiler schon
> klar zu machen.

Der Typ von "...." ist fest vorgegeben, und für die Interpretation der 
Library ist nur massgeblich, was bei deren Übersetzung angegeben war. 
Das setzt der Freiheit Grenzen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Andreas Kaiser wrote:

> Ein "char *" ist auch dann zu einem "signed char *"
> imkompatibel, wenn beide technisch identisch sind.

Ist in C inzwischen auch so, nur nicht ganz so strikt -- daher ist
es eben kein Fehler, sondern nur eine Warnung.  Ein Programm, das
sich auf irgendeine signedness des Typs char verlässt, ist aber
explizit nicht mehr portabel.  Wenn einem die Portabilität egal ist,
muss man sich natürlich nicht drum kümmern (dann könnte man die
Warnung auch abschalten), aber ich behaupte hier mal, dass mehr als
95 % der Programmierer, die sich über die Warnung wundern, gar nicht
wissen, welche Art Portabilitätsprobleme sie sich damit einhandeln
könnten und daher gut beraten sind, die Warnung nicht zu ignorieren.

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.