Re[5]: Откуда эта лютая любовь к знаковым целым?
От: Alexander G Украина  
Дата: 07.05.20 13:05
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

AG>>Intel Optimization Reference Manual, September 2019

MA> Именно там эту информацию и можно найти. И в более старых мануалах тоже например.

Но там ведь написано, что signed выключают macro-fusion, а unsigned её разрешают.

https://software.intel.com/sites/default/files/managed/9e/bc/64-ia-32-architectures-optimization-manual.pdf


Страница 3-14

Example 3-10. Macro-fusion, Unsigned Iteration Count

Notes:

1. Signed iteration count inhibits macro-fusion.
2. Unsigned iteration count is compatible with macro-fusion.
3. CMP MEM-IMM, JGE inhibit macro-fusion.
4. CMP REG-IMM, JAE permits macro-fusion

Русский военный корабль идёт ко дну!
Re[6]: Откуда эта лютая любовь к знаковым целым?
От: vopl Россия  
Дата: 07.05.20 13:24
Оценка:
Здравствуйте, Erop, Вы писали:

E>Суть в том, что в подавляющем числе мест, где нужны числа, int просто логичнее, чем беззнаковое. И интуитивно понятнее, и безопаснее и всё такое.


Ну, хз. То ли получаются те самые фломастеры, которые разные на вкус и цвет, то ли теперь надо определиться, что за "числа, которые нужны" и почему они без мнимой части, ато вдруг программист будет не только вычитание делать, но еще и корни начнет извлекать..
Re[6]: Откуда эта лютая любовь к знаковым целым?
От: vopl Россия  
Дата: 07.05.20 13:38
Оценка:
Здравствуйте, Erop, Вы писали:

V>>И последний: если бы int тоже был бы закольцован, то есть при переполнении просто бы отбрасывались переполненные биты, как, например, в Расте — ты все равно бы знаковым отдал предпочтение?


E>Конечно. За исключением логики оптимизатора, int и так на x86 закольцован


Аяй, погоди, че то у меня прорвало шаблон немного

На мой взгляд в конструкции "Надо нумеровать члены последовательности" + "целое число из диапазона [INT_MIN, INT_MAX]" + "кольцо модулей по вычетам какой-то неизвестной степени двойки" лишнее-то, как раз кольцо...


так все таки, речь не идет о "диапазоне против кольца"?

"целое число из закольцованного диапазона [INT_MIN, INT_MAX]" vs "целое число из закольцованного диапазона [0, UINT_MAX]"

так надо было думать если закольцованность не при чем?
Re[2]: Откуда эта лютая любовь к знаковым целым?
От: Pavel Dvorkin Россия  
Дата: 07.05.20 13:58
Оценка: :)
Здравствуйте, Михaил, Вы писали:

М>В прошлом помнится нередко возникали траблы, когда переменная "случайно" уходила в область отрицательных значений и, будучи unsigned, превращалась в очень большое полож число, нарушая логику. Туда же и ==/!= в циклах вместо > <. С тех пор завел правило всегда юзать signed into, кроме случаев, когда нужно уместить большое число, которое не умещается в signed. В остальных случаях Unsigned не дают никакого выигрыша -Только писать больше приходится.


Вот-вот.
Во времена оные (то есть Windows 3.1) писал я одну программу. Решил, что координаты и размер окна при выходе из программы должны сохраняться в ini-файл , а при следующем запуске оттуда браться, чтобы окно оказалось на экране в том же месте. Реестр тогда не использовали для этих целей.
Прихожу однажды, запускаю программу — запускается, но окна на экране нет. Совсем нет.
Ставлю breakpoint в WM_CREATE — все в порядке, окно создается. Ставлю breakpoint в WM_DESTROY — нет, не приходит.
Появляются нехорошие мысли о самоуничтожающихся окнах без WM_DESTROY и о том, что я что-то крупно не понимаю в программировании для Win API. Мысли давлю. Но куда, черт возьми, это окно девалось ?

В общем, некоторое время я над этим размышлял, пока не догадался заглянуть в .ini файл. Оказывается, левая X — координата окна перед сохранением была отрицательной, а при записи в файл делалось преобразование к unsigned. В итоге окно по X оказалось с координатой примерно 60000 и было, видимо, показано на экране в соседней комнате
With best regards
Pavel Dvorkin
Re[4]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.05.20 14:02
Оценка: 5 (1) +1
Здравствуйте, Alexander G, Вы писали:

AG>>>- fused операция при сравнении и переходе: while (i > 0) или for ( i ; i < 10 ; i++ ) CMP и JCC выполняются как одна операция только для беззнаковых.


MA>> Это не так и при чем уже довольно давно.


AG>Intel Optimization Reference Manual, September 2019


I. Я понимаю, что авторам документации Intel явно искривили руки ещё в утробе, но всё равно такие документы надо читать по тому, что в них написано, а не додумывать самому:

• Intel microarchitecture code name Nehalem supports the following enhancements in macrofusion:
— CMP can be fused with the following conditional jumps (that was not supported in Intel Core
microarchitecture):
• JL or JNGE
• JGE or JNL
• JLE or JNG
• JG or JNLE
— Macro-fusion is support in 64-bit mode.


То есть до Nehalem в 64-битке вообще было пофиг — оно не работало в принципе — но работало для проверок типа JNC (aka JAE) в 32 битах, а начиная с Nehalem — начало работать и для стандартных проверок как для знаковых. Ваши процессоры старее, чем Nehalem? Если да, то зачем?

Там ещё чуть дальше табличка для SandyBridge и потомков, не забудьте и её.

II. А с чего вы решили, что знаковые операции будут компилироваться так, как Intel рисует? Они рисуют только для своего компилятора. Вот я взял GCC5 и повторил их пример:

extern volatile int a;
void foo() {
  for (int i = 0; i < 1000; i++) {
    a++;
  }
}


Ассемблерная выдача:

foo:
        mov     edx, 1000
.L2:
        mov     eax, DWORD PTR a[rip]
        add     eax, 1
        mov     DWORD PTR a[rip], eax
        sub     edx, 1
        jne     .L2
        rep ret


Видимо, как раз из-за этих старых хохмочек они предпочитают JNE?

Я могу даже заставить её сохранять переменную цикла:

extern int* a;
void foo() {
  for (int i = 0; i < 1000; i++) {
    a[i]++;
  }
}


Результат:

foo:
        mov     rdx, QWORD PTR a[rip]
        xor     eax, eax
.L2:
        inc     DWORD PTR [rdx+rax*4]
        inc     rax
        cmp     rax, 1000
        jne     .L2
        ret


Всё равно JNE, хоть тресни.

Вывод: все эти химеры нужны только для ассемблерных писателей под древние процессоры (в которые входят и авторы компиляторов). Остальным уже обеспечено, что влияние знаковости устранено для основных типовых случаев.
The God is real, unless declared integer.
Re[5]: Откуда эта лютая любовь к знаковым целым?
От: Alexander G Украина  
Дата: 07.05.20 14:28
Оценка:
Здравствуйте, netch80, Вы писали:

N>I. Я понимаю, что авторам документации Intel явно искривили руки ещё в утробе, но всё равно такие документы надо читать по тому, что в них написано, а не додумывать самому:


Да, нужно было дочитать, принимается.

N>То есть до Nehalem в 64-битке вообще было пофиг — оно не работало в принципе — но работало для проверок типа JNC (aka JAE) в 32 битах, а начиная с Nehalem — начало работать и для стандартных проверок как для знаковых. Ваши процессоры старее, чем Nehalem? Если да, то зачем?


N>Там ещё чуть дальше табличка для SandyBridge и потомков, не забудьте и её.


N>II. А с чего вы решили, что знаковые операции будут компилироваться так, как Intel рисует? Они рисуют только для своего компилятора. Вот я взял GCC5 и повторил их пример:


По идее компилятор должен сам оптимизировать, т.к. это Assembly/Compiler Coding Rule, не Source Coding Rule.

Но я проверил, что MSVC генерирует то, что написано.
Русский военный корабль идёт ко дну!
Re[3]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.05.20 14:31
Оценка:
Здравствуйте, Erop, Вы писали:

TB>>Ты на беззнаках даже тупо от ЭН до нуля проитерироваться не можешь без дополнительного бубна.


E>А как же "оператор стремления к нулю"?

E>
E>size_t i = n;
E>while(i-->0) {
E>    // Тут что-то делаем с n-1, n-2, ..., 1, 0
E>}
E>


С этим оператором для N-битного числа ты не сможешь сделать, чтобы первая итерация была 2**N-1 (например, в 32-битке нельзя сделать, чтобы первая итерация была для i == 0xFFFF_FFFF): тебе придётся зайти с i == 0, и while() немедленно отвергнет (а выйдя ты как раз 0xFFFF_FFFF и найдёшь в i, но будет поздно).
А иногда бывает и такая потребность, приходится учитывать. Так что нет тут полного счастья без постпроверки.
The God is real, unless declared integer.
Re[6]: Откуда эта лютая любовь к знаковым целым?
От: Mystic Artifact  
Дата: 07.05.20 14:36
Оценка: 5 (1) +1
Здравствуйте, Alexander G, Вы писали:

Там есть радел про macro-fusion и какие конкретно пары понимаются. И уже по моему с хасвелла парятся все тоже самое + JL/JG. Этой части раньше не было, и ее расширили. Как-то так. Сейчас с телефона, неудобно искать.
Re[6]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.05.20 14:36
Оценка:
Здравствуйте, Alexander G, Вы писали:

N>>II. А с чего вы решили, что знаковые операции будут компилироваться так, как Intel рисует? Они рисуют только для своего компилятора. Вот я взял GCC5 и повторил их пример:

AG>По идее компилятор должен сам оптимизировать, т.к. это Assembly/Compiler Coding Rule, не Source Coding Rule.

Угу, я об этом же. Компилятору можно говорить int или unsigned int, он всё равно внутри может пересчитать в реальные диапазоны значений и оптимизировать уже на основании этих результатов.
Кстати, Clang 6 при -O уже сразу включил векторизацию. (На -Og ещё не включил, и видно JNE в обоих случаях.)

AG>Но я проверил, что MSVC генерирует то, что написано.


Даже так... я подумал, что они таки выхлоп ICC брали. Слишком хорошо подумал, увы.
Хорошо, что у меня при выборе между GCC и Clang на ближайшие N лет таких проблем нет ;\
The God is real, unless declared integer.
Re[7]: Откуда эта лютая любовь к знаковым целым?
От: Alexander G Украина  
Дата: 07.05.20 14:49
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

MA>Там есть радел про macro-fusion и какие конкретно пары понимаются. И уже по моему с хасвелла парятся все тоже самое + JL/JG. Этой части раньше не было, и ее расширили. Как-то так. Сейчас с телефона, неудобно искать.


Да, уже показали, зачеркнул устаревшее утверждение в исходном своём сообщении.
Русский военный корабль идёт ко дну!
Re[7]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.05.20 14:55
Оценка: +1
Здравствуйте, vopl, Вы писали:

V>>Причем тут size_t и почему ты считаешь, что он "более уместен"? Результат вычитания двух указателей имеет тип ptrdiff_t. Можно легко представить платформу, где первый гораздо меньше второго.

V>size_t меньше ptrdiff_t? Вряд ли. Стандарт требует чтобы этот тип вмещал размер любого объекта, включая тот самый массив, разницу индексов которого вмещает ptrdiff_t. Таким образом, он гарантированно не меньше ptrdiff_t.

Пусть у нас 16-битная платформа (чтобы числа не были страшными) и адреса от 0 до 65535.
Для size_t достаточно 16 бит. Для ptrdiff_t, чтобы поддержать все значения от +65535 до -65535 — 17 бит.

Проблема общеизвестная, и её решают тем, что ни одному объекту не позволяют достигать в размере 1/2 адресного пространства (причём требование именно "меньше space/2", а не "не больше space/2"! потому что в дополнительном коде +32768 тоже не влезет). Но это значит, что для size_t достаточно на один бит меньше (15, а не 16). Ч.Т.Д.

(Реально на современных платформах общего пользования это обеспечивается тем, что половина адресного пространства занята ядром, а в остальном есть ещё код, стек и т.п.
Но на embedded запросто получить и более хитрые конфигурации, в которых проблема может вылезти в полный рост.)

V>Он "более уместен" потому что не имеет знака, который на самом деле не нужен. Из за этого, например, мой компилятор не генерирует дополнительную проверку на отрицательность в том цикле.


А с чего бы это быть той проверке? Есть масса других вариантов обойти.
The God is real, unless declared integer.
Re[5]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.05.20 14:58
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Здравствуйте, netch80, Вы писали:


H>>>>Во-вторых, иногда нужно не-валидное значение чего-то, что по смыслу неотрицательно. И для этого я лично использую «-1». И если переменная равна ему, то значит значение невалидное. Такая штука с unsigned не проканает, если не вводить всякие magic digits конечно.

PJ>>>std::optional<uint>
N>>И терять 4-8 байт вместо одного бита ;[
PJ>корретное поведение вместо креша того стоит.

И часто вам нужен размах больше половины значений соответствующего типа?
The God is real, unless declared integer.
Re[4]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.05.20 15:06
Оценка:
Здравствуйте, Alexander G, Вы писали:

N>>Именно в C и C++ у знаковых принципиально лучше с точки зрения производительности, что позиция, что программист всегда позаботился о переполнениях, позволяет массу оптимизаций, типа замены a+1>a на true. Были отзывы о получении 20-50% выигрыша на этом в отдельных характерно интересных случаях.

AG>Ха, интересно, про неопределённость роловера для знаковых и определённость для беззнаковых уловил.
AG>Интересно, как далеко можно пойти на этом неопределённом переполнении знаковых, но принял к сведению.

Ну вот пример набора оптимизаций. Реально их ещё больше.

AG>(MSVC похоже никуда не идёт, он тупо делает реальное сравнение в обоих случаях a + 1 > a)


Ну, похоже, MSVC сильно отстал. Хотя это какого года версия? Они с 2015 кричат про переход на SSA, там многое должно заметно поменяться.

N>>Что сравнивали-то? Intel рисует (почти) противоположное — для длинного умножения времена одинаковы, а для короткого (которому пофиг на знак) на 1-2 такта меньше (3 вместо до 5).

AG>Обычное деление достаточно больших чисел int64_t / uint64_t, компиляция MSVC x64, беззнаковые ощутимо быстрее. Нужно воспроизвести?

Это уже речь про деление, а перед этим было про умножение

Вообще, если настроение, киньте код, я сверю в своих условиях.

AG>>>С точки зрения корректности, знаковые как бы ограждают от одного типа ошибок (отрицательное число -> переполнение), но вносят другие (отрицательное число -> выход за диапазон), шило на мыло.

N>>А у положительного переполнение у обоих. А так как мелкие числа, включая отрицательные, чаще, чем крупные, то знаковые числа заведомо выигрывают.
AG>В положительную сторону переполняются одинаково. Что до отрицательной, неожиданное отрицательное число, чуть-чуть вышедшее за диапазон, даёт больше вреда, чем такое же положительное, при тех же условиях вышедшее в огромные значения.

А как может положительное "выйти в огромные значения", если нет перехода через границу?
А если есть переход или хотя бы подозрение на него...
Опять же похвалю GCC и Clang — совершенно гениальная придумка (особенно если учесть вариант с тремя разными типами), такое в стандарты надо было ещё лет 20 назад вогнать. И от MS, боюсь, ещё долго не дождаться.
The God is real, unless declared integer.
Re[4]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.05.20 15:15
Оценка: 1 (1)
Здравствуйте, Vamp, Вы писали:

V>void baz(char );


V>void foo(char* begin, char* end) {

V> for (int i = 0; i < (end — begin); ++i)
V> baz(begin[i]);

V>Данный код предполагает, что расстояние между началом и концом уменьшается в 32 бита, и в рамках этого предположения работает отлично. Если заменить тип управляющей переменной на unsigned int, скорость кода заметно уменьшится. Связано это с тем, что компилятору придется контролировать переполнение на каждой операции (как правило, путем засовывания числа в отдельный короткий регистр), так как беззнаковые целые разрешают переполнение. Классическая рекомендация — использовать знаковое целое.


Вот этого я, кстати, не понял. Можно разъяснить?
Я прогнал оба варианта через GCC, он генерирует практически идентичный выхлоп и в 32- и в 64-битном режиме, точнее, в 32 полностью совпадают инструкции в цикле, в 64 — расширяются до 64 бит при сравнении разным образом (movsx при знаковом, чистое mov при беззнаковом).

В остальном согласен.

V>Кроме того, в С++ в математических операциях, смешивающих знаковые и беззнаковые числа, знаковые приводятся к беззнаковым, после чего операция выполняется по правилам беззнаковых.


Это да, полная диверсия.
The God is real, unless declared integer.
Re[8]: Откуда эта лютая любовь к знаковым целым?
От: vopl Россия  
Дата: 07.05.20 15:26
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, vopl, Вы писали:


V>>>Причем тут size_t и почему ты считаешь, что он "более уместен"? Результат вычитания двух указателей имеет тип ptrdiff_t. Можно легко представить платформу, где первый гораздо меньше второго.

V>>size_t меньше ptrdiff_t? Вряд ли. Стандарт требует чтобы этот тип вмещал размер любого объекта, включая тот самый массив, разницу индексов которого вмещает ptrdiff_t. Таким образом, он гарантированно не меньше ptrdiff_t.

N>Пусть у нас 16-битная платформа (чтобы числа не были страшными) и адреса от 0 до 65535.

N>Для size_t достаточно 16 бит. Для ptrdiff_t, чтобы поддержать все значения от +65535 до -65535 — 17 бит.

N>Проблема общеизвестная, и её решают тем, что ни одному объекту не позволяют достигать в размере 1/2 адресного пространства (причём требование именно "меньше space/2", а не "не больше space/2"! потому что в дополнительном коде +32768 тоже не влезет). Но это значит, что для size_t достаточно на один бит меньше (15, а не 16). Ч.Т.Д.


Да, согласен . На один бит. Но не "гораздо меньше".

N>(Реально на современных платформах общего пользования это обеспечивается тем, что половина адресного пространства занята ядром, а в остальном есть ещё код, стек и т.п.

N>Но на embedded запросто получить и более хитрые конфигурации, в которых проблема может вылезти в полный рост.)

V>>Он "более уместен" потому что не имеет знака, который на самом деле не нужен. Из за этого, например, мой компилятор не генерирует дополнительную проверку на отрицательность в том цикле.


N>А с чего бы это быть той проверке? Есть масса других вариантов обойти.


Ну хз. Тут видно, один лишний test https://gcc.godbolt.org/z/HZBYFv
Re[9]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.05.20 15:44
Оценка:
Здравствуйте, vopl, Вы писали:

V>Да, согласен . На один бит. Но не "гораздо меньше".


Так в 2 раза же.

V>>>Он "более уместен" потому что не имеет знака, который на самом деле не нужен. Из за этого, например, мой компилятор не генерирует дополнительную проверку на отрицательность в том цикле.


N>>А с чего бы это быть той проверке? Есть масса других вариантов обойти.


V>Ну хз. Тут видно, один лишний test https://gcc.godbolt.org/z/HZBYFv


А, на входе... я тело цикла смотрел, там идентично. Что там на входе делается — обычно, считается, на производительность не влияет — посмотрите какой ужас компилируется при векторизации на входе и выходе основного цикла — и всё равно это считается безвредным

Но тут проблема не типа как такового — к моменту прихода оптимизаций типы уже стёрты, а диапазона значений. Проверка выбрасывается в правом случае потому, что после конверсии end-beg в беззнаковое оказывается, что в условии немедленного выхода "0 >= (unsigned size_t)(end-beg)" случай "больше" невозможен и его можно не проверять. Но это корректно только до тех пор, пока реально end >= beg! Вы косвенно, за счёт неявной конверсии к беззнаковому в этом сравнении, гарантируете это условие (и получите очень больно, если нарушите его).
В нормальном современном языке можно было бы это условие записать явно, как часть предусловий на вызов функции, и тогда 1) проверка была бы выброшена и со знаковой переменной цикла, 2) компилятор получил бы шанс проверить вызовы функции на корректность.
The God is real, unless declared integer.
Re[4]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 07.05.20 16:06
Оценка:
Здравствуйте, Erop, Вы писали:

E>2) С-шные unsigned типы -- это не целые. Это кольцо по модулю вычетов.


Это важно исключительно там, где не исключено переполнение. Если переполнение исключено, нет никакого смысла говорить о кольце.

E>Почему тебе кажется более естественным нумеровать элементы последовательности элементами такого кольца, а не ограниченными по модулю целыми числами, для меня загадка...


Возможно, потому, что последовательности традиционно нумеруются с единицы или нуля...
Re[5]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 07.05.20 16:10
Оценка:
Здравствуйте, Erop, Вы писали:

E>Вот есть у меня подпоследовательность. Почему бессмысленно ссылаться на "элемент, предшествующий первому элементу нашей подпоседовательности"?


Можно, почему нельзя. Но это именно под последовательность, с относительным доступом. Для такого доступа совершенно естественны числа со знаком, здесь я против них ничего не имею.
Re[10]: Откуда эта лютая любовь к знаковым целым?
От: Reset  
Дата: 07.05.20 17:21
Оценка:
N>Но тут проблема не типа как такового — к моменту прихода оптимизаций типы уже стёрты, а диапазона значений. Проверка выбрасывается в правом случае потому, что после конверсии end-beg в беззнаковое оказывается, что в условии немедленного выхода "0 >= (unsigned size_t)(end-beg)" случай "больше" невозможен и его можно не проверять. Но это корректно только до тех пор, пока реально end >= beg! Вы косвенно, за счёт неявной конверсии к беззнаковому в этом сравнении, гарантируете это условие (и получите очень больно, если нарушите его).

Не очень понимаю, про какие проверки вы все говорите: godbolt (смотреть на серенькое и желтенькое, т.е. содержимое цикла). IMHO, разница между int и unsigned в том, что unsigned — это целое по модулю 2^32 и при переполнении он должен оставаться 32-х битным, поэтому компилятор работает с unsigned в отдельном 32-х битном регистре и там появляется лишняя команда (на самом деле регистр тот же, но приходится из 32-х бит делать 64, как результат — лишняя команда). Для int переполнение — это UB, поэтому он использует сразу 64-х битный регистр, который будет вести себя как 32-х битный, если нет переполнения. Поэтому дополнительной команды там нет, ну, и в случае переполнения UB проявится в том, что будет поведение не как у 32-х битного числа.
Re[10]: Откуда эта лютая любовь к знаковым целым?
От: vopl Россия  
Дата: 07.05.20 17:23
Оценка:
Здравствуйте, netch80, Вы писали:

V>>Да, согласен . На один бит. Но не "гораздо меньше".


N>Так в 2 раза же.


Ок, в 2 раза, на один бит.

V>>>>Он "более уместен" потому что не имеет знака, который на самом деле не нужен. Из за этого, например, мой компилятор не генерирует дополнительную проверку на отрицательность в том цикле.


N>>>А с чего бы это быть той проверке? Есть масса других вариантов обойти.


V>>Ну хз. Тут видно, один лишний test https://gcc.godbolt.org/z/HZBYFv


N>А, на входе... я тело цикла смотрел, там идентично. Что там на входе делается — обычно, считается, на производительность не влияет — посмотрите какой ужас компилируется при векторизации на входе и выходе основного цикла — и всё равно это считается безвредным


Мелочь — не считается?

N>Но тут проблема не типа как такового — к моменту прихода оптимизаций типы уже стёрты, а диапазона значений. Проверка выбрасывается в правом случае потому, что после конверсии end-beg в беззнаковое оказывается, что в условии немедленного выхода "0 >= (unsigned size_t)(end-beg)" случай "больше" невозможен и его можно не проверять.


Именно проблема типа. Более конкретно — знакового или беззнакового типа. Еще более конкретно — проблема выбора этого типа программистом. Оптимизации непричем. Вот именно, что проверка в случае беззнаковых сразу выбрасывается так как она не имеет смысла. А в случае знаковых — нужна, и она производится, с помощью того самого лишнего теста. Могло бы не быть лишнего теста, если бы использовался "правильный" тип, но программист засунул туда знаковый. Именно по этому я считаю беззнаковый более подходящим для, цитирую ТС:

счетчики, индексы и прочие... размеры, количества и прочее...


Вот она и та самая бритва окама сыграла — если не нужна знаковость — не используй, потому что она не бесплатна, как минимум, этим одним лишним тестом. Вот оно, то самое "не хуже, а иногда чуть-лучше".

N>Но это корректно только до тех пор, пока реально end >= beg! Вы косвенно, за счёт неявной конверсии к беззнаковому в этом сравнении, гарантируете это условие (и получите очень больно, если нарушите его).


Не получу) У меня только "счетчики, индексы, размеры, количества...", у меня только такие ситуации в рассмотрении, в которых end >= beg. Сейчас я не физик или математик, мне не нужно "натуральное число". Завтра попадется задача, где будет нужно знаковое число — ну просто возьму его и буду использовать. Не то чтобы я упорот, просто немного ошарашивают рекомендации типа "всегда только знаковые типы!". Да ёлы-палы, пацаны! Никогда не говори "никогда"!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.