Forum: Compiler & IDEs Konstantes Char-Array in Hex initialisieren


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
ich bin mal wieder an die (gar nicht mal so weitläufigen) Grenzen meines 
Verständnisses für C gestoßen:

Ich kann eine Funktion mit einem anonymen konstanten String aufrufen, 
z.B.
1
glcd_putstr("Hallo");

allerdings führt der Aufruf mit einem anderen String
1
glcd_putstr((unsigned char *) {0x48,0x61,0x6C,0x6C,0x6F,'\0'});
zu einer (vermutlich völlig berechtigten) Warnung, obwohl beide Strings 
auf den ersten Blick völlig identisch zu sein scheinen. Die Reaktion des 
Programms ist auch die erwartete.

Wo liegt mein Denkfehler?

Viele Grüße
Nicolas

von DirkB (Gast)


Lesenswert?

Und wie lautet die Warnung?

irgendwas mit unsigned oder signed?

von troll (Gast)


Lesenswert?

interessante Frage...

Nicolas S. schrieb:
> zu einer (vermutlich völlig berechtigten) Warnung
die da wäre?

von Walter T. (nicolas)


Lesenswert?

Dann scheint es zumindest nicht auf den ersten Blick offensichtlich zu 
sein:

Warnung  1  initialization makes pointer from integer without a cast 
[enabled by default]    ...
Warnung  2  (near initialization for '(anonymous)') [enabled by default] 
...
Warnung  3  excess elements in scalar initializer [enabled by default] 
....

Dateinamen und Zeile habe ich herausgelöscht, um es übersichtlicher zu 
machen.

Der Compiler will doch nicht ernsthaft von mir, daß ich den Datentyp in 
jedem Array-Element einzeln vorgebe?

von Marco M. (marco_m)


Lesenswert?

Du verstehst das was da abgeht völlig falsch. Du gibst dem Compiler 
einen Array-Initialisierer und sagst ihm, daß das in Wirklichkeit ein 
'char*' sein soll. Der Compiler nimmt jetzt das erste Element des Arrays 
und interpretiert das als char* (da kommt die Meldung über den pointer 
der aus einem integer ohne cast gemacht wird her). Die anderen Elemente 
sind aber jetzt übrig (daher die Meldung über 'excess elements').

Wenn das jetzt bei dir funktionieren sollte, dann ist das reiner Zufall. 
Es ist nämlich totaler Quatsch und undefiniertes Verhalten.

Richtig ist dagegen:

[c]
glcd_putstr((char[]) {0x48,0x61,0x6C,0x6C,0x6F,'\0'});
{/c}

weil dies dem Compiler sagt, den Initialisierer als array von char zu 
interpretieren. Dieses Konstrukt ist übrigens eine GCC-Spezifische 
Erweiterung, die hier dokumentiert wird:

http://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html#Compound-Literals

und bei anderen Compilern nicht funktioniert.

von Walter T. (nicolas)


Lesenswert?

Hallo Marco,
danke für den Tip. Also mal wieder ein alter Fehler aus der Gruppe 
"manchmal sind arrays äquivalent zu Pointern und manchmal nicht". Ich 
denke in drei, vier Jahrzehnten falle ich nicht mehr darauf herein.

Viele Grüße
Nicolas

von Rrolf Magnus (Gast)


Lesenswert?

Marco M. schrieb:
> Dieses Konstrukt ist übrigens eine GCC-Spezifische
> Erweiterung, die hier dokumentiert wird:

Nein, der ist Standard. Steht übrigens gleich im ersten Satz des von dir 
verlinkten Abschnitts.

von Marco M. (marco_m)


Lesenswert?

Rrolf Magnus schrieb:
> Marco M. schrieb:
>> Dieses Konstrukt ist übrigens eine GCC-Spezifische
>> Erweiterung, die hier dokumentiert wird:
>
> Nein, der ist Standard. Steht übrigens gleich im ersten Satz des von dir
> verlinkten Abschnitts.

Ah ja, allerdings nur für C99.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Marco M. schrieb:
>> Nein, der ist Standard. Steht übrigens gleich im ersten Satz des von dir
>> verlinkten Abschnitts.
>
> Ah ja, allerdings nur für C99.

Nicht nur, auch der aktuelle Standard (C11) unterstützt die Compound-
Literals, welche somit noch nicht veraltet sind ;-)

von Peter D. (peda)


Lesenswert?

Nicolas S. schrieb:
> Also mal wieder ein alter Fehler aus der Gruppe
> "manchmal sind arrays äquivalent zu Pointern und manchmal nicht".

Das ist doch ganz einfach.
Wenn Du ein Array ablegen willst, mußt Du auch dafür Speicherplatz 
reservieren. Ein Pointer speichert aber nur eine Adresse.

Du kannst zusätzlich einen Pointer auf das Array zeigen lassen, aber das 
Array muß ja irgendwo stehen. Es steht ja nicht in der Luft.

Also:
Array: reserviert Speicherplatz für alle Elemente
Pointer: reserviert nur Speicherplatz für einen Zeiger.

Implizit benötigt ein Pointer immer auch mindestens ein Array, auf 
dessen Elemente er irgendwann mal zeigt.


Peter

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.