2016-04-05 19 views
10

Ich habe über ein Stück Code kam die folgende Initialisierung macht:String initializer mit geschweiften Klammern

static const uint8_t s[] = {"Some string"}; 

Ich würde erwarten, dass es zu interpretieren, wie folgt: Die rechte Seite ist ein Array von char Zeiger mit einzelnen passend Element, das auf ein String-Literal "Some string" zeigt. Während der linke Teil ein Array von uint8_t ist. Dann erwarte ich, dass das erste Element von s einen abgeschnittenen Wert des Zeigers auf das Zeichenfolgenliteral erhält, was zu einem unerwarteten Verhalten im folgenden Code führt, unter der Annahme, dass s eine Zeichenfolge ist.

Ich habe den folgenden Testcode gemacht:

#include <stdint.h> 
#include <stdio.h> 

static const uint8_t s1[] = "String1"; 
static const uint8_t s2[] = { "String2" }; 
int main(void){ 

    printf("%p, %p\n", s1, s2); 
    printf("%s, %s\n", s1, s2); 

    return 0; 
} 

Für meine Überraschung scheint es, dass es nicht geschieht. Nicht nur der Code wird richtig funktionieren, sondern auch die Demontage zeigt, dass sowohl s1 als auch s2 als die entsprechenden Strings in identischer Weise initialisiert werden.

Ist das etwas gcc spezifisch? Ist es C-Syntax erlaubt, das einzelne String-Literal in {} zu nehmen und es trotzdem als String-Literal zu interpretieren?

+0

Fügen Sie eine zweite Zeichenfolge hinzu, und sehen Sie, was passiert: 'static const uint8_t s2 [] = {" String2 "," String3 "};' – LPs

+0

@LPs Ja, habe es versucht. –

+0

Ok, DevSolar hat dir gegeben, was du brauchst. – LPs

Antwort

16

Zitiert aus N1570 (der endgültige Entwurf von C11), 6.7.9 Initialisierung (emphasis mir):

  1. Ein Array von Zeichentyp durch ein Zeichen initialisiert werden kann String Literal oder UTF-8 String Literal, optional in Klammern eingeschlossen. Aufeinander folgende Bytes des Zeichenfolgenliterals (einschließlich des abschließenden Nullzeichens , wenn Platz vorhanden ist oder wenn das Array eine unbekannte Größe hat) initialisieren Sie die Elemente des Arrays.
+2

Ok, das beantwortet die Frage explizit. Vielen Dank. –

8

Die Antwort der Sonne Qingyao erwähnt richtig, dass Sie zusätzliche Klammern solche initializer hinzufügen können. Es lohnt sich, das erwähnen nicht nur auf Arrays anwenden:

int x = { 0 }; 

compiles obwohl das Element initialisiert wird, ist kein Array. Dies ist dank der folgenden Klausel:

6.7.9.11 Die Initialisierung für einen Skalar ist ein einziger Ausdruck sein, gegebenenfalls in Klammern eingeschlossen.

Aber warum sollte so etwas erlaubt sein? Die Antwort ist, macht dies möglich Werte zu initialisieren, mit einer einzigen Syntax:

T x = { 0 }; 

Werke für jeden T und Null-initialisiert alles (für structs, jedes Mitglied, für Arrays initialisiert jedes Element, für skalare Typen, nur der Wert).

+1

Sie können einen Verweis hinzufügen: '11 Der Initialisierer für einen Skalar soll ein einzelner Ausdruck sein, der optional in geschweifte Klammern eingeschlossen ist. –

+0

@sun qingyao Ich denke, dass diese Referenz als vollständige Antwort gelten würde. Obwohl die initialisierte Entität technisch kein Skalar ist .... –

Verwandte Themen