Сообщение Re[4]: offsetof() без UB от 24.03.2025 15:24
Изменено 27.03.2025 13:30 kov_serg
Re[4]: offsetof() без UB
Здравствуйте, _NN_, Вы писали:
_>>Компилятор должен помогать программисту в его работе быть скучным и предсказуемым, а не удивлять его сюрпризами. Короче шланг гавно.
_NN>Есть вариант делать предсказуемое поведение и жаловаться на неоптимальносгенерируемый код.
_NN>Каков ваш выбор ?
Совершенно очевидно, что выбор должен быть явным. Если вы хотите контролировать переполнение явно это указывайте компилятору.
_NN>Например, у нас беззнаковые числа имеют предсказуемость при переполнении и в итоге получаем лишние инструкции процессора от которых не избавиться.
_NN>Пример: https://gcc.godbolt.org/z/11rWEjzdv
Если вы знаете рабочие диапазоны то переполнений не будет.
А если нужна длинная арифметика надо bignum тип иметь. Что бы он мог как строки динамически расширяться при необходимости.
_NN>Расскажите как часто вы пользуетесь определённым переполнением знаковых чисел, а не полагаетесь на неопределённое поведение в случае переполнения.
Приходится преобразовывать к безнаковому, благодоря тому что знаковый считается UB
_NN>Есть библиотека jtckdint, а начиная с C++26 будет Checked integer arithmetic в стандартной библиотеке.
_NN>Уже пользуетесь и пишете скучный и предсказуемый код ?
Да в 146% случаев нужен скучный, предсказуемый код, который выполняет именно то что его попросили.
_>>Компилятор должен помогать программисту в его работе быть скучным и предсказуемым, а не удивлять его сюрпризами. Короче шланг гавно.
_NN>Есть вариант делать предсказуемое поведение и жаловаться на неоптимальносгенерируемый код.
_NN>Каков ваш выбор ?
Совершенно очевидно, что выбор должен быть явным. Если вы хотите контролировать переполнение явно это указывайте компилятору.
checked int a; // проверяйте of флаг и т.п.
module int b; // обычная модульная арифметика, в ней нет переполнений
saturated int c; // арифметика с насыщением, не коммутативна и т.п. приколы
_NN>Например, у нас беззнаковые числа имеют предсказуемость при переполнении и в итоге получаем лишние инструкции процессора от которых не избавиться.
_NN>Пример: https://gcc.godbolt.org/z/11rWEjzdv
Если вы знаете рабочие диапазоны то переполнений не будет.
А если нужна длинная арифметика надо bignum тип иметь. Что бы он мог как строки динамически расширяться при необходимости.
_NN>Расскажите как часто вы пользуетесь определённым переполнением знаковых чисел, а не полагаетесь на неопределённое поведение в случае переполнения.
Приходится преобразовывать к безнаковому, благодоря тому что знаковый считается UB
typedef signed long long rint;
typedef unsigned long long ruint;
enum { UNSIGNED_OVERFLOW=1,SIGNED_OVERFLOW=2 };
struct rintf { rint r; char f; } ;
rintf adc(int* res,rint a,rint b,char c) {
char f=0; ruint ua=(ruint)a, ub=(ruint)b, ur=ua+ub+(c&1), us=~(~((ruint)0)>>1);
if (ur<ua || ur<ub) f|=UNSIGNED_OVERFLOW;
if ((ua&us)==(ub&us) && ((ua&us)!=(ur&us))) f|=SIGNED_OVERFLOW;
return rintf{ (rint)ur, f };
}
rintf sbb(rint a,rint b,char c) {
char f=0; ruint ua=(ruint)a, ub=(ruint)b, ur=ua-ub-(c&1), us=~(~((ruint)0)>>1);
if (ua<ub || ua<ur) f|=UNSIGNED_OVERFLOW;
if ((ua&us)!=(ub&us) && ((ua&us)!=(ur&us))) f|=SIGNED_OVERFLOW;
return rintf{ (rint)ur, f };
}
_NN>Есть библиотека jtckdint, а начиная с C++26 будет Checked integer arithmetic в стандартной библиотеке.
_NN>Уже пользуетесь и пишете скучный и предсказуемый код ?
Да в 146% случаев нужен скучный, предсказуемый код, который выполняет именно то что его попросили.
Re[4]: offsetof() без UB
Здравствуйте, _NN_, Вы писали:
_>>Компилятор должен помогать программисту в его работе быть скучным и предсказуемым, а не удивлять его сюрпризами. Короче шланг гавно.
_NN>Есть вариант делать предсказуемое поведение и жаловаться на неоптимальносгенерируемый код.
_NN>Каков ваш выбор ?
Совершенно очевидно, что выбор должен быть явным. Если вы хотите контролировать переполнение явно это указывайте компилятору.
_NN>Например, у нас беззнаковые числа имеют предсказуемость при переполнении и в итоге получаем лишние инструкции процессора от которых не избавиться.
_NN>Пример: https://gcc.godbolt.org/z/11rWEjzdv
Если вы знаете рабочие диапазоны то переполнений не будет.
А если нужна длинная арифметика надо bignum тип иметь. Что бы он мог как строки динамически расширяться при необходимости.
_NN>Расскажите как часто вы пользуетесь определённым переполнением знаковых чисел, а не полагаетесь на неопределённое поведение в случае переполнения.
Приходится преобразовывать к безнаковому, благодоря тому что знаковый считается UB
_NN>Есть библиотека jtckdint, а начиная с C++26 будет Checked integer arithmetic в стандартной библиотеке.
_NN>Уже пользуетесь и пишете скучный и предсказуемый код ?
Да в 146% случаев нужен скучный, предсказуемый код, который выполняет именно то что его попросили.
_>>Компилятор должен помогать программисту в его работе быть скучным и предсказуемым, а не удивлять его сюрпризами. Короче шланг гавно.
_NN>Есть вариант делать предсказуемое поведение и жаловаться на неоптимальносгенерируемый код.
_NN>Каков ваш выбор ?
Совершенно очевидно, что выбор должен быть явным. Если вы хотите контролировать переполнение явно это указывайте компилятору.
checked int a; // проверяйте of флаг и т.п.
module int b; // обычная модульная арифметика, в ней нет переполнений
saturated int c; // арифметика с насыщением, не коммутативна и т.п. приколы
_NN>Например, у нас беззнаковые числа имеют предсказуемость при переполнении и в итоге получаем лишние инструкции процессора от которых не избавиться.
_NN>Пример: https://gcc.godbolt.org/z/11rWEjzdv
Если вы знаете рабочие диапазоны то переполнений не будет.
А если нужна длинная арифметика надо bignum тип иметь. Что бы он мог как строки динамически расширяться при необходимости.
_NN>Расскажите как часто вы пользуетесь определённым переполнением знаковых чисел, а не полагаетесь на неопределённое поведение в случае переполнения.
Приходится преобразовывать к безнаковому, благодоря тому что знаковый считается UB
typedef signed long long rint;
typedef unsigned long long ruint;
enum { UNSIGNED_OVERFLOW=1,SIGNED_OVERFLOW=2 };
struct rintf { rint r; char f; } ;
rintf adc(rint* res,rint a,rint b,char c) {
char f=0; ruint ua=(ruint)a, ub=(ruint)b, ur=ua+ub+(c&1), us=~(~((ruint)0)>>1);
if (ur<ua || ur<ub) f|=UNSIGNED_OVERFLOW;
if ((ua&us)==(ub&us) && ((ua&us)!=(ur&us))) f|=SIGNED_OVERFLOW;
return rintf{ (rint)ur, f };
}
rintf sbb(rint a,rint b,char c) {
char f=0; ruint ua=(ruint)a, ub=(ruint)b, ur=ua-ub-(c&1), us=~(~((ruint)0)>>1);
if (ua<ub || ua<ur) f|=UNSIGNED_OVERFLOW;
if ((ua&us)!=(ub&us) && ((ua&us)!=(ur&us))) f|=SIGNED_OVERFLOW;
return rintf{ (rint)ur, f };
}
_NN>Есть библиотека jtckdint, а начиная с C++26 будет Checked integer arithmetic в стандартной библиотеке.
_NN>Уже пользуетесь и пишете скучный и предсказуемый код ?
Да в 146% случаев нужен скучный, предсказуемый код, который выполняет именно то что его попросили.