Подтвердить что ты не робот

C Препроцессор Снять трейлинг-запятую

У меня есть макрос вроде этого:

#define C( a... ) ( char *[] ){ a, 0 }

Это работает для непустых аргументов:

C( "a", "b" ) => ( char *[] )( "a", "b", 0 }

Но я хочу удалить конечную запятую, если она содержит пустой аргумент:

C() => ( char *[] ){ , 0 }

Возможно ли это?

4b9b3361

Ответ 1

По крайней мере, в GCC 5.4.0, на Cygwin (default -std=gnu11), это похоже на то, что вы хотите (при условии, что я понимаю ваш вопрос правильно):

#define C( a... ) ( char *[] ){ a 0 }
                                 ^ no comma!    
C( "a", "b", ) 
           ^ comma here
=> ( char *[] )( "a", "b", 0 }

C() 
=> ( char *[] ){ 0 }

Протестировано с помощью gcc -E и других параметров командной строки.

Изменить Как отметил @KerrekSB, это не переносимо. Документы препроцессора GCC говорят об этом (выделено мной):

Вышеприведенное объяснение неоднозначно в отношении случая, когда единственным параметром макроса является параметр переменных аргументов [как в этой ситуации - ред.], так как бессмысленно пытаться отличить, не является ли вообще никакой аргумент пустой аргументацией или отсутствующий аргумент. В этом случае стандарт C99 ясно, что запятая должна оставаться, однако существующее расширение GCC используется для проглатывания запятой. Таким образом, CPP сохраняет запятую, когда она соответствует конкретному стандарту C, и оставляет его в противном случае.

Таким образом, это работает отлично в GCC, но может и не на других компиляторах. Однако для меня это работает с gcc -std=c90 -E (или c99, или c11).