A #define в C с тремя точками

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))

это определение для этих 2 макросов; позже в коде LOGI и LOGW используются таким образом

LOGI("accelerometer: x=%f y=%f z=%f",
                                event.acceleration.x, event.acceleration.y,
                                event.acceleration.z);

и таким образом

LOGW("Unable to eglMakeCurrent");

так как я стараюсь избегать сложных макросов и #define В общем, я не могу понять, что на самом деле означает этот макрос. Какова роль для обозначения 3 точек здесь? Что это #define изменить в коде?

очевидно, я знаю, что 3 точки используются для указания и неопределенного количества аргументов, но я не знаю, как понять эту ситуацию.

1 ответов


введен стандарт C99 поддержка variadic макросы, т. е. функциональные макросы, которые могут принимать переменное количество аргументов.

со ссылкой на последний проект стандартные C, раздел 6.10.3:

если список идентификаторов в определении макроса не заканчивается многоточие, количество аргументов (включая эти аргументы состоит из токенов предварительной обработки) в вызове a функциональный макрос должен быть равен количество параметров в макросе определение. В противном случае в вызове должно быть больше аргументов чем есть параметры в определении макроса (исключая ...). Должен существовать a) токен предварительной обработки, который завершает вызов.

идентификатор __VA_ARGS__ происходит только в списке замены функциональный макрос, использующий многоточие в параметры.

...

если есть ... в списке идентификаторов в определении макроса, затем конечные аргументы, включая любую разделяющую запятую токены предварительной обработки объединяются в один элемент:переменной доводы. Число аргументов, Объединенных таким образом, таково, что, после слияния число аргументов на один больше числа параметров в определении макроса (исключая ...).

и в следующем пункте:

идентификатор __VA_ARGS__ что происходит в списке замены быть обработанным как если бы это был параметр, и переменные аргументы сформируйте токены предварительной обработки, используемые для его замены.

таким образом, вы можете вызвать LOGI или LOGW С таким количеством аргументов, как вам нравится, и все они будут расширены в месте, указанном в определении ссылкой на __VA_ARGS__.