Условная компиляция в зависимости от sizeof(double)

Есть макрос (#define ...) где-то в недрах с Arduino IDE или основных заголовочных файлов, которая говорит мне, что во время компиляции(!), если двойной тип данных для конкретной платформы/платы-это настоящий двойной точности с плавающей запятой (64 разрядность), или "всего лишь" псевдоним для одинарной точности с плавающей запятой (32 бит шириной)?

С Arduino и то, и другое может иметь место. 8-битные платы AVR имеют double равную float точность , платы на базе ARM (например, Arduino Zero) поддерживают "истинную" двойную точность.

Я работаю над библиотекой, которая реализует некоторую битовую обработку чисел с плавающей запятой (как одинарной, так и двойной точности). Из-за низкоуровневой природы проблемы должны существовать отдельные функции для float и double. Я хотел бы сделать что - то вроде этого:

uint32_t function_for_float(float f) {
    // function body here...
}

#if defined(HAS_64_BIT_DOUBLE)
uint64_t function_for_double(double d) {
    // function body here...
}
#endif

Таким образом, ошибка времени компиляции будет сгенерирована, если кто-то попытается использовать версию "double" на платформах, которые не поддерживают тип данных "true" double. Я хочу, чтобы ошибка компилятора была сгенерирована, потому что функция function_for_double() будет молча делать "неправильную вещь" при подаче float с одинарной точностью, что потенциально приведет к трудным для отладки проблемам.

Прямо сейчас я определяю макро-константу для каждой соответствующей платы, которой владею, например:

#if defined(ARDUINO_SAMD_ZERO) \
 || defined(SAMD_FEATHER_M0_EXPRESS) \
 || defined(ADAFRUIT_FEATHER_M4_EXPRESS)
    #define HAS_64_BIT_DOUBLE
#endif

Но это уродливо и не перспективно (новые платы могут/станут доступны...).

Есть предложения?

, 👍2

Обсуждение

Это на самом деле не вопрос Arduino. Arduino использует g++ для компиляции, поэтому ваш вопрос действительно "может ли g++ сделать это?" Судя по [этому](https://stackoverflow.com/questions/4079243/how-can-i-use-sizeof-in-a-preprocessor-macro) - не совсем. Вы можете утверждать, что double не 8 байт (я проверил это), но не делать выбор, если нет другого хитрого способа сделать это., @Nick Gammon

@NickGammon: Спасибо за ссылку. У меня на самом деле есть " static_assert(sizeof(double) == 8) в коде моей "двойной функции". Однако тогда полный файл library .cpp не будет компилироваться на платформах, где double` имеет только четыре байта. Именно это и заставило меня задуматься об условном дополнении в первую очередь. Я хотел бы генерировать ошибку компилятора только в том случае, если sombody пытается использовать двойную версию, когда он не должен. Где-то в Arduino наверняка должно быть определено, что double равно float? Я надеюсь(г) использовать это как крюк каким-то образом..., @Andy


1 ответ


Лучший ответ:

4

Двойной тип данных почти повсеместно имеет длину 8 байт, так что вы можете просто

#if !__AVR__
# define HAS_64_BIT_DOUBLE
#endif

Однако Gcc предоставляет более специфичный макрос: __SIZEOF_DOUBLE__, который имеет то же значение, что и sizeof(double). Но я не знаю , обеспечивается ли это другими компиляторами.

,

Идеально! Я буду использовать макросы __SIZEOF_DOUBLE__ и __SIZEOF_DOUBLE__, даже если они специфичны для gcc/g++. В любом случае, Arduino IDE использует g++ в качестве своего бэкенда, так что для меня этого "достаточно"., @Andy

Только что проверил, что " __SIZEOF_DOUBLE__ == 4 на Arduino Pro Mini (AVR 328p) и __SIZEOF_DOUBLE__ == 8` на Adafruit Feather M0 (ARM Cortex-M0+ / SAMD21). Большое спасибо! Я выбрал ваш ответ как правильный., @Andy