Genera avviso del compilatore se manca la virgola di inizializzazione dell'array const char*

Genera avviso del compilatore se manca la virgola di inizializzazione dell'array const char*

Avvolgimento di ogni const char* tra parentesi dovrebbe risolvere il problema come mostrato nel seguente snippet:

static const char* const stateNames[5] =
{
    ("Init state"),
    ("Run state"),
    ("Pause state")     //comma missing
    ("Pause state3"),
    ("Error state")
};

Se dimentichi una virgola, riceverai un errore di compilazione simile a:error: called object is not a function or function pointer

DIMOSTRAZIONE IN DIRETTA

Nota che se dimentichi la virgola, ciò che effettivamente accade è che C concatenerà effettivamente le due (o più) stringhe fino alla virgola successiva o alla fine dell'array. Ad esempio, supponiamo di dimenticare la virgola come mostrato di seguito:

static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state" //comma missing
    "Pause state3" //comma missing
    "Error state"
};

int main(void)
{  
    printf("%s\n", stateNames[0]);
    return 0;    
}

Questo è ciò che gcc-9.2 genera (altri compilatori generano codice simile):

.LC0:
        .string "Init state"
        .string "Run state"
        .string "Pause statePause state3Error state" ; oooops look what happened
        .quad   .LC0
        .quad   .LC1
        .quad   .LC2
main:
        push    rbp
        mov     rbp, rsp
        mov     eax, OFFSET FLAT:.LC0
        mov     rdi, rax
        call    puts
        mov     eax, 0
        pop     rbp
        ret

È chiaro che le ultime tre stringhe sono concatenate e l'array non ha la lunghezza che ti aspetteresti.


Potresti consentire al compilatore di contare l'array e generare un messaggio di errore in caso di risultato imprevisto:

enum { STATE_AMOUNT = 4 };

static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state"    // <--- missing comma
    "Error state",
};

_Static_assert( sizeof stateNames / sizeof *stateNames == STATE_AMOUNT,
        "oops, missed a comma" );

Vedi questo thread per idee per implementare _Static_assert se il tuo compilatore è molto vecchio e non lo supporta.

Come bonus, questo può anche aiutare quando aggiungi nuovi stati ma ti dimentichi di aggiornare la tabella delle stringhe. Ma potresti anche voler esaminare X Macros.


Ho sempre usato un riferimento a un array di dimensioni esplicite per risolvere questo problema.

// no explicit size here
static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state",
    "Error state",
};
static const char* const (&stateNameVerifier)[STATE_AMOUNT] = stateNames;

http://coliru.stacked-crooked.com/a/593fc2eac80782a6

main.cpp:10:32: error: reference to type 'const char *const [5]' could not bind to an lvalue of type 'const char *const [4]'
static const char* const (&stateNameVerifier)[STATE_AMOUNT] = stateNames;