ViKo 1 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Допустим, в макрофункции производятся некие вычисления - умножение, деление. И ее результат должен быть больше нуля и меньше или равным 2 ^32. Как задать параметры макрофункции, чтобы гарантировать, что компилятор при расчетах не вышел за пределы unsigned long long? Если их несколько. Задачу для ограничений результатов могу так сделать: (FUN > UINT_MAX) ? UINT_MAX : (FUN > 0 ? FUN : 1) А проверку внутри макрофункции? Наверное, никак? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 63 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба А проверку внутри макрофункции? Наверное, никак? Для одной или двух переменных еще выгодно проверять входящие, если больше - то дешевле вычислить с большей разрядностью, потому что надо проверять все комбинации границ значений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Для одной или двух переменных еще выгодно проверять входящие, если больше - то дешевле вычислить с большей разрядностью, потому что надо проверять все комбинации границ значений. Так и хочу, потому и использую ULL. Но как этот предел проверить? У меня 3 переменных. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 63 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Для каждого выражения свои. Например х*y/z - чтобы не вышли за 64бита, достаточно чтобы все значения были не более 32 бита а если х*y*z и значения 32 бита - чтобы не вышли за 64бита, надо контролировать чтобы сумма разрядности чисел не превысила 64, можно логарифмы сложить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Сообразил. Перемежать операции умножения и деления UINT чисел, чтобы промежуточный расчет принципиально не мог выйти за пределы ULLONG числа. Но чтобы и точность не потерялась, смотреть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 63 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Я думал, что это подразумевалось :) Но это слишком узкий взгляд - у вас же не все переменные могут получить значения с максимальной разрядностью. Но тут не очень понятна конечная цель. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Да, если буду делить не в конце, потеряю точность. Правильнее сначала перемножать, потом логарифмы складывать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Для вычисления константных выражений (видимо их Вы и имели в виду? так как у макроопределений в си нет никаких типов - это просто текстовые подстановки) компилятор использует определённый тип данных, например unsigned long long для целых. И за его пределы он не может выйти естественно никак по определению. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Для вычисления константных выражений (видимо их Вы и имели в виду? так как у макроопределений в си нет никаких типов - это просто текстовые подстановки) компилятор использует определённый тип данных, например unsigned long long для целых. И за его пределы он не может выйти естественно никак по определению. Пусть называются константные выражения. Выйти - отчего же не может? Задам ему 1E12 * 1E12, вот и вышел. Переполнился. Мне нужно знать, что вычисление не переполнилось при обработке препроцессором. Допустим, как определять, есть идеи. Но как эту проверку встроить в макрофункцию? #define Delay(V, U) delay(V * U * F / 4 / 10E9) Здесь можно проверить: V * U <= 2^32 * 4 * 10E9 / F P.S. тут я смешиваю два вопроса, проверить, что результат укладывается в целое число, и не допустить, чтобы в процессе вычисления не было переполнения длинного числа. А есть способ выдать число в Build Output компилятора? Видимо, вопрос сводится к следующему: Как вставить assert внутрь macro? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 апреля, 2018 Опубликовано 7 апреля, 2018 · Жалоба Хорошо, #warning Keil может вывести, этим можно пользоваться для вывода ограничений на параметры. Самому считать не придется. Остальное уже не важно. А вот #error так вывести не получится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
501-й 0 8 апреля, 2018 Опубликовано 8 апреля, 2018 · Жалоба Видимо, вопрос сводится к следующему: Как вставить assert внутрь macro? /* ct-assert.h */ /* макросы проверяют, что ex константа и не 0 */ #if !defined( CT_ASSERT_EXPR ) #define CT_ASSERT_EXPR(ex) ((struct { int assert:(ex) ? 1 : -1; } *)0 ? 0 : 0) #endif /* !defined( CT_ASSERT_EXPR ) */ #if !defined( CT_ASSERT_DECL ) #define CT_ASSERT_DECL(ex) extern char ct_assert_[ CT_ASSERT_EXPR(ex)+1 ] #endif /* !defined( CT_ASSERT_DECL ) */ #if !defined( CT_ASSERT ) #define CT_ASSERT(ex) (void)CT_ASSERT_EXPR(ex) #endif /* !defined( CT_ASSERT ) */ /* End of file ct-assert.h */ Используй макрос CT_ASSERT_EXPR(). Он всегда равен 0, если скомпилировался без ошибок. Илья Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться