Каракальный вопрос типа C
-
28-10-2019 - |
Вопрос
Как сделать приведенную ниже функцию универсальной для uint8_t, uint16_t, uint32_t, int8_t, int16_t, int32_t и float_t?
Как видите, я не люблю повторять одну и ту же логику в каждом случае.Единственная разница в каждом случае - это кастинг.
В идеале мне хотелось бы иметь решение, соответствующее стандарту C и, следовательно, переносимое.Любые идеи приветствуются.
Спасибо.
родовое словоРешение
Ну, вы можете извлечь приведенные типы:
GenracodicetagpreИли, если различные типы образуют непрерывный диапазон значений от 0, вы даже можете создать два массива указателей на функции и сделать:
GenracodicetagpreПримечания:
- Вам все равно придется написать по две функции для каждого типа, хотя при желании они легко сгенерируются макросами.
- Вряд ли стоит использовать этот небольшой код.
- Я выбрал
int64_t
, поскольку он может представлять все значения всех используемых вами целочисленных типов, поэтому преобразования вint64_t
никогда не отбрасывают информацию и никогда не изменяют результат сравнения относительно выполнения того же сравнения в тип источника. Но если вы также хотите охватитьuint64_t
, вы не можете использовать один и тот же тип для всего, поскольку не существует целочисленного типа, который мог бы представлять все значения всех целочисленных типов. Вам также понадобится отдельная функцияtestLimitsf
дляfloat
, возможно, с использованиемlong double
в качестве общего типа для обеспечения гибкости в будущем. - [Edit: я только что понял, предполагая, что IEEE-754,
double
действительно может точно представлять все значения всех используемых вами типов. Таким образом, с небольшим ограничением переносимости, вы можете использоватьtestLimitsf
для всего и работать с двойными] - Вы уверены, что перед сравнением стоит преобразовать (например) в
uint8_t
? Либо значение находится в диапазоне для кодаuint8_t
, и в этом случае вам не нужно преобразовывать, вы можете просто провести сравнение. В противном случае значение не входит в диапазон, и в этом случае уменьшение по модулю делает сравнение немного бессмысленным, за исключением особых случаев 0 и -1. Так что, возможно, оно того стоит, если что-то, о чем вы не сказали, делает это так, но мне это кажется подозрительным. - В комментарии вы сказали: «Я пытаюсь сделать эту функцию более эффективной». Это может пойти против этого. Логически возможно встроить код
testLimits
, а также вызовы функций приведения в кодswitch
, но я бы не стал на это рассчитывать.
Другие советы
Нет простого способа выполнить такое обобщенное программирование на языке C.Если вы беспокоитесь о техническом обслуживании, это может быть редким случаем, когда подходит макрос.
Почему бы не использовать макрос?
родовое словоВ следующей редакции стандарта (C1x) будет добавлена поддержка общих выражений типа (пример из Википедии):
родовое словоgcc имеет предварительную поддержку C1x.Я думаю, что _Generic еще не поддерживается, но помните об этом на будущее.