Forum: Compiler & IDEs warning: pointer targets differ in signedness


von Thomas B. (detritus)


Lesenswert?

Hallo zusammen

Mein avr-gcc spuckt ne Warnung aus, die ich nicht verstehe.

Erstmal der Code(heruntergekürzt):
1
volatile u16 wandlungswert=19;  //Das Ding ist global
2
3
int main(void)
4
{
5
  u8 text_lcd[20];
6
  itoa(wandlungswert, text_lcd, 10);
7
  lcd_puts(text_lcd);
8
}

Jedes mal, wenn das Feld text_lcd an ne Funktion übergeben wird, haut 
mir der Compiler ne Warnung rein, die für den itoa so aussieht:

pwmadc.c:93: warning: pointer targets in passing argument 2 of 'itoa' 
differ in signedness

analog dazu der lcd_puts().

Naja... mein Englisch hilft mir hier nicht weiter, google auch nicht. 
Wenn ich das Textfeld dann mal als s8 deklariere(eh Blödsinn), kriege 
ich die gleiche Fehlermeldung.
Funktionieren tut alles, ich würd nur mal gerne wissen, was ich da am 
Heiligen C verbrochen habe.

von Karl H. (kbuchegg)


Lesenswert?

> pointer targets in passing argument 2 of 'itoa'
> differ in signedness

pointer target   =   das worauf ein Zeiger zeigt

in passing argument 2 of itoa  = die Rede ist also vom 2.ten Argument
                                 welches an itoa übergeben wird

differ =   unterscheidet sich

in signedness =    das ist in der Tat etwas schwieriger zu übersetzen.
                   Gemeint ist: da gibt es einen signed / unsigned
                   Unterschied.


In Summe: Du übergibst einen Pointer auf einen signed Datentyp.
          Die Funktion möchte aber einen Pointer auf einen
          unsigned Datentyp.
          Oder umgekehrt: Du übergibst einen Pointer auf unsigned
          und die Funktion möchte einen Pointer auf signed.


Da die Rede vom 2.ten Argument zu itoa ist, wird es wohl hilfreich
sein, sich mal die Deklaration von itoa anzusehen:

char* itoa    ( int zahl, char* string, int radix );

Aha. Das 2.te Argument sollte ein Pointer auf char sein.

Da ich deine typedefs nicht kenne, kann ich nur raten, was ein
u8 bzw. ein s8 sein soll. Wenn ich raten muß, würde ich mal
so raten:

typedef unsigned char u8;
typedef signed char s8;

Keines von beiden qualifiziert sich aber als ganz normaler char.
Und daher ist ein u8* nicht dasselbe wie ein char*, und ein
s8* ist auch nicht dasselbe wie ein char*. Ein char* kann
nur durch einen char* ersetzt werden.

Da du aber weist, dass das in Ordnung geht, wenn du deinen u8*
an itoa übergibst, kannst du den Compiler mit einem cast
ruhigstellen:
1
  itoa(wandlungswert, (char*)text_lcd, 10);

oder aber, du nimmst den char so wie er gedacht ist: Als generischen
Datentyp für eine Variable die den ASCII Code eines Zeichens aufnimmt,
bei der es egal ist, ob da ein Vorzeichenbit enthalten ist, weil
damit sowieso nicht gerechnet wird, sondern einfach nur Ein/Ausgabe
damit gemacht wird.
1
int main(void)
2
{
3
  char text_lcd[20];
4
  itoa(wandlungswert, text_lcd, 10);
5
  lcd_puts(text_lcd);
6
}

von Thomas B. (detritus)


Lesenswert?

Ahso... Dann gibt es hier als 8Bit breite Datentypen
1
- unsigned char
2
- signed char
3
- char

Wobei für den char nicht festgelegt ist, ob er ein Vorzeichen hat oder 
nicht?

Meine typedefs sehen tatsächlich so aus:
1
typedef unsigned char  u8;
2
typedef   signed char  s8;

(Dass mir mein Englisch nicht weiterhilft, hab ich eigentlich so 
gemeint, dass ich es übersetzen kann, aber trotzdem das Problem nicht 
verstehen konnte)

Jedenfalls vielen Dank für die ausführliche (und schnelle) Antwort!

von Karl H. (kbuchegg)


Lesenswert?

Thomas B. wrote:
> Ahso... Dann gibt es hier als 8Bit breite Datentypen
>
>
1
> - unsigned char
2
> - signed char
3
> - char
4
>

Yep.

>
> Wobei für den char nicht festgelegt ist, ob er ein Vorzeichen hat oder
> nicht?

Yep.
Aber egal wie es festgelegt wird
   char <> signed char
   char <> unsigned char

( <> bedeutet: ist nicht gleich)

> Meine typedefs sehen tatsächlich so aus:
>
1
> typedef unsigned char  u8;
2
> typedef   signed char  s8;
3
>

Mach das nicht. Seit einiger Zeit gibt es in C definierte
Datentypen für solche Zwecke, in denen man sich um die
Bitgröße eines Datentyps kümmern möchte:

#include <stdint.h>


int8_t      ein signed Integer mit 8 Bit
uint8_t     ein unsigned Integer mit 8 Bit
int16_t     ein signed Integer mit 16 Bit
uint16_t    .....
....

http://en.wikipedia.org/wiki/Stdint.h

Damit entfällt die Notwendigkeit sich selbst solche Datentypen
zu definieren und zu warten. Und vor allen Dingen: Alle Programmierer
benutzen dieselben Typen.

von Thomas B. (detritus)


Lesenswert?

Karl heinz Buchegger wrote:
> Thomas B. wrote:

>> Meine typedefs sehen tatsächlich so aus:
>>
1
>> typedef unsigned char  u8;
2
>> typedef   signed char  s8;
3
>>
>
> Mach das nicht. Seit einiger Zeit gibt es in C definierte
> Datentypen für solche Zwecke, in denen man sich um die
> Bitgröße eines Datentyps kümmern möchte:
>
> #include <stdint.h>
>
>
> int8_t      ein signed Integer mit 8 Bit
> uint8_t     ein unsigned Integer mit 8 Bit
> int16_t     ein signed Integer mit 16 Bit
> uint16_t    .....
> ....
>
> http://en.wikipedia.org/wiki/Stdint.h
>
> Damit entfällt die Notwendigkeit sich selbst solche Datentypen
> zu definieren und zu warten. Und vor allen Dingen: Alle Programmierer
> benutzen dieselben Typen.


Ok, dann werd ich mich in Zukunft dran halten. Nur zum Tippen sind die 
Dinger extrem nervig, mit dem _ mitten in der Bezeichnung...

von Simon K. (simon) Benutzerseite


Lesenswert?

Man kann auch mit -funsigned-char kompilieren...

EDIT: Was aber nicht die Warnung abschaltet *HUST

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.