Sto facendo alcuni esperimenti con la nuova parola chiave _Generic
e sono incappato in un caso speciale riguardante più valutazioni. Vedere i seguenti:Effetti collaterali nelle espressioni generiche
#include <stdio.h>
#define write_char(c) _Generic(c, char: putchar, const char: putchar)(c)
int main(void)
{
const char *s = "foo";
write_char(*s++);
write_char(*s++);
write_char(*s++);
putchar('\n');
}
Questo compila bene e produce il risultato atteso con GCC:
$ gcc -std=c11 -Wall plusplus.c -o plusplus
$ ./plusplus
foo
D'altra parte, Clang emette un avvertimento grande clacson:
$ clang -std=c11 plusplus.c -o plusplus
plusplus.c:9:18: warning: multiple unsequenced modifications to 's'
[-Wunsequenced]
write_char(*s++);
^~
plusplus.c:3:32: note: expanded from macro 'write_char'
#define write_char(c) _Generic(c, char: putchar, const char: putchar)(c)
...
Eppure il il risultato è come previsto:
$ ./plusplus
foo
Ho controllato the draft of the standard, che dice (a pag. 97 del PDF):
L'espressione di controllo di una selezione generica non viene valutata.
Questo sembra indirizzare con precisione il problema degli effetti collaterali a macro (ad esempio, MIN
e MAX
).
Ora, posso ignorare tranquillamente l'avviso di Clang o mi sbaglio?
Suona come si dovrebbe essere segnalando un problema al team di sviluppo Clang, piuttosto che ignorarlo. Potresti essere il primo ad aver riscontrato il problema. Cosa succede quando scrivi 'putchar (* s ++)'? Questo genera anche l'avviso? Presumibilmente no. –
Penso che tu abbia scoperto un bug in clang! – haccks
I fan di '_Generic' potrebbero essere vagamente ricordati di questa domanda, quindi ci collegherò qui e potranno decidere se è correlato (non penso che lo sia): http://stackoverflow.com/questions/24743520/incompatible-pointer-types-passing-in-generic-macro/ –