Forum: Mikrocontroller und Digitale Elektronik verstehe diese Compiler-Warnung nicht


von brechbunkt (Gast)


Lesenswert?

Hallo,

ich habe den nachfolgenden array aus strings und möchte den jeweiligen 
Tag ausgeben können, was doch eigentlich kein Problem sein sollte:
1
char *weekDay[] = {"ERR", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
2
3
print_dbg("Heute ist ");
4
print_dbg(weekDay[1]);

Soweit funktioniert das ganze auch, aber ich bekomme komischer weise 
diese Warnung:
1
Warning      array subscript has type 'char'


Ich kann mir allerdings nicht erklären, was der Compiler hier zu meckern 
hat. Kann mir jemand einen Tipp vielleicht geben?

von Dirk (Gast)


Lesenswert?

Der Compiler interpretiert bei dir die "1" als signed char, was zu 
unsinnigen negativen Indizes (>127) führen kann.

von (prx) A. K. (prx)


Lesenswert?

Und weshalb sollte der Compiler die lexikalische Konstante 1 als signed 
char betrachten? Per Sprachdefinition von C ist die vom Typ int.

von Peter II (Gast)


Lesenswert?

Dirk schrieb:
> Der Compiler interpretiert bei dir die "1" als signed char, was zu
> unsinnigen negativen Indizes (>127) führen kann.

auch negative Indizes sind gültig.

von (prx) A. K. (prx)


Lesenswert?

Nicht bei Arrays, nur bei Pointern, und das Überlaufverhalten von 
vorzeichenbehafteten Datentypen ist nicht definiert, also nicht per se 
als negativ zu sehen.

Diese in meinen Augen etwas fragwürdige Warning scheint tatsächlich Teil 
von GCC zu sein. Weshalb sie hier auslösen sollte ist jedoch unklar. 
Aber vielleicht ist der hier gezeigte Code ja nicht der eigentliche 
Code, nur "so ähnlich". Oder der relevante Teil fehlt.

von Peter II (Gast)


Lesenswert?

A. K. schrieb:
> Diese in meinen Augen etwas fragwürdige Warning scheint tatsächlich Teil
> von GCC zu sein.

im Test tritt es aber nicht auf:
1
#include <stdio.h>
2
3
char *weekDay[] = {"ERR", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
4
5
int main()
6
{
7
   printf("Heute ist ");
8
   printf(weekDay[1]);
9
10
   return 0;
11
}

wie ist denn print_dbg definiert?

von (prx) A. K. (prx)


Lesenswert?

Peter II schrieb:
> im Test tritt es aber nicht auf:

Kann ja auch nicht, weil weit und breit kein Index vom Typ char zu sehen 
ist. So aber schon, und da kriegt man die Warnung dann auch (-Wall):
1
int main()
2
{
3
   char c = 1;
4
5
   printf("Heute ist ");
6
   printf(weekDay[c]);
7
8
   return 0;
9
}
Ich schrieb ja schon, dann brechbunkt hier möglicherweise den 
eigentlichen Code zwecks Demonstration stark vereinfacht und damit die 
Ursache gleich mit beseitigt hatte.

von brechbunkt (Gast)


Lesenswert?

Ja stimmt, ich habe den Code vereinfachen wollen. Normaler weise schaut 
er so aus:
1
print_dbg(weekDay[ tm->tm_wday ]);

Der Wert tm_wday ist ein 8 Bit Wert von einem RTC.

Wenn ich die Zeile allerdings (dank eurer Hilfe) so abändere, ist alles 
gut:
1
print_dbg(weekDay[(int)(tm->tm_wday)]);

von ....bitte ausfüllen.... (Gast)


Lesenswert?

brechbunkt schrieb:
> Der Wert tm_wday ist ein 8 Bit Wert von einem RTC.

Und der ist von Typ Char!?!

von Stefan E. (sternst)


Lesenswert?

brechbunkt schrieb:
> Wenn ich die Zeile allerdings (dank eurer Hilfe) so abändere, ist alles
> gut:

Besser wäre es allerdings, tm_wday von vornherein einen sinnvollen 
8-Bit-Typ zu geben, nämlich "unsigned char" oder "uint8_t".

von (prx) A. K. (prx)


Lesenswert?

Stefan Ernst schrieb:
> Besser wäre es allerdings, tm_wday von vornherein einen sinnvollen
> 8-Bit-Typ zu geben, nämlich "unsigned char" oder "uint8_t".

Mit dieser Idee kommst du rund 40 Jahre zu spät. Allerdings ist der 
Unterschied bei Werten zwischen 0 und 6 nicht wirklich relevant.

Zumal für mich nicht nachvollziehbar ist, wieso negative ints gut sind 
und negative chars schlecht.

von tumb (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Besser wäre es allerdings, tm_wday von vornherein einen sinnvollen
> 8-Bit-Typ zu geben, nämlich "unsigned char" oder "uint8_t".

Ganz und gar nicht. Der Index muss int sein, kein char - dann 
klappts auch ohne Warnung bzw. Laufzeit-Fehler.

von (prx) A. K. (prx)


Lesenswert?

Warum muss er int sein? Damit GCC die Schnauze hält? Er muss grad gross 
genug sein, um die Werte 0-6 darstellen zu können.

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


Lesenswert?

A. K. schrieb:
> Stefan Ernst schrieb:
>> Besser wäre es allerdings, tm_wday von vornherein einen sinnvollen
>> 8-Bit-Typ zu geben, nämlich "unsigned char" oder "uint8_t".
>
> Mit dieser Idee kommst du rund 40 Jahre zu spät.

Das Feld tm_wday der struct tm gemäß C-Standard ist vom Typ
"int".

Unser TE wird also wohl irgendwie sein eigenes Süppchen kochen.

> Zumal für mich nicht nachvollziehbar ist, wieso negative ints gut sind
> und negative chars schlecht.

Ich denke nicht, dass es um negative chars schlechthin geht, aber
um mögliche Probleme bei der sign extension zu `int'.  Bei
1
char c = 240;
2
3
   ...
4
   return array[c];

könnte das nämlich zu unliebsamen Überraschungen führen, wenn das
default `char' vorzeichenbehaftet ist, und davor zu warnen ist
die Sache m. E. Wert.

von Stefan E. (sternst)


Lesenswert?

A. K. schrieb:
> Stefan Ernst schrieb:
>> Besser wäre es allerdings, tm_wday von vornherein einen sinnvollen
>> 8-Bit-Typ zu geben, nämlich "unsigned char" oder "uint8_t".
>
> Für diese Idee kommst du rund 40 Jahre zu spät.

Falls du auf die struct tm der time.h hinaus willst, dort ist tm_wday 
ein int, kein char. Er verwendet also irgendwas eigenes oder 
modifiziertes, und es spricht nichts dagegen, es zu ändern.

von (prx) A. K. (prx)


Lesenswert?

Jörg Wunsch schrieb:
> signed char c = 240;

Da liegt das Hase im Pfeffer. Denn eigentlich müsste er an dieser 
Stelle warnen. Das aber traut sich ohne -pedantic nicht einmal GCC, 
weils sonst an Warnungen nur so hagelt.

von (prx) A. K. (prx)


Lesenswert?

Stefan Ernst schrieb:
> Falls du auf die struct tm der time.h hinaus willst, dort ist tm_wday
> ein int, kein char.

Und int kann nicht negativ werden?

von Stefan E. (sternst)


Lesenswert?

tumb schrieb:
> Stefan Ernst schrieb:
>> Besser wäre es allerdings, tm_wday von vornherein einen sinnvollen
>> 8-Bit-Typ zu geben, nämlich "unsigned char" oder "uint8_t".
>
> Ganz und gar nicht. Der Index muss int sein, kein char - dann
> klappts auch ohne Warnung bzw. Laufzeit-Fehler.

Unsinn. Ein "unsigned char", "signed char", "int8_t" oder "uint8_t" 
würde auch keine Warnung bringen.

von Stefan E. (sternst)


Lesenswert?

A. K. schrieb:
> Stefan Ernst schrieb:
>> Falls du auf die struct tm der time.h hinaus willst, dort ist tm_wday
>> ein int, kein char.
>
> Und int kann nicht negativ werden?

Es geht bei dieser Warnung nicht darum, dass der Index negativ sein 
kann. Es geht darum, dass bei char die Signedness nicht spezifiziert 
ist.

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


Lesenswert?

A. K. schrieb:
> Jörg Wunsch schrieb:
>> signed char c = 240;
>
> Da liegt das Hase im Pfeffer. Denn eigentlich müsste er an *dieser*
> Stelle warnen.

Das "signed" hatte ich dann noch rausgeworfen.  Wenn man das
hinschreibt, nimmt der GCC es als Hinweis, dass man sich was dabei
gedacht hat ;), und warnt nicht.  Die Warnung kommt wirklich nur für
ein "unqualifiziertes" `char', und sie soll offenbar ausschließlich
darauf hinweisen, dass bei der Benutzung eines solchen als Array-Index
eine implizite Konvertierung nach `int' erfolgt mit all ihren
potenziellen Tücken.

von ....bitte ausfüllen.... (Gast)


Lesenswert?

A. K. schrieb:
> Warum muss er int sein? Damit GCC die Schnauze hält?
Es ist nie gut, irgendwelche Warnungen im Code zu haben. Ein Programm 
sollte immer ohne jegliche Warnungen compilieren. Alles andere ist 
schlechter Stil.

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.