Size_t и переполнение

Здравствуйте!
Решила жить правильно и для всяких индексов-размеров для контейнеров STL, а также массивов стала использовать переменные/константы типа size_t. Т.е. unsigned int. И тут же получила (((

for (size_t i = 0; i < vec.size(); ++i) { ... }

работает прекрасно, а в обратную сторону

for (size_t i = vec.size() - 1; i >= 0; --i) { ... }

получается бесконечный цикл, поскольку i >= 0 истинно всегда для unsigned. Поставить i != 0, а после цикла отдельно обрабатывать первый элемент вектора, или шаманить с переменной цикла внутри тела цикла — это мне кажется неправильно.

Подскажите как правильно?
На самом деле вопрос даже не про контейнеры STL, а про использование беззнаковых типов в подобных ситуациях.

for (size_t i = vec.size(); i != 0; --i) {arr[i-1] = ... }

В ряде случаев можете использовать знаковый тип ptrdiff_t вместо size_t, правда это приведет к варнингам.

Поняла, спасибо.
Тоже не самый элегантный подход ((
Странно, такой старый язык (это ведь еще с С такая проблема?), а нормального решения так и не придумали. Хоть бы какую стандартную функцию сделали: типа «зафиксировано переполнение?». Тоже и к переполнению знаковых переменных.

А вот еще маленький вопрос примерно на ту же тему. В STL для размеров/индексов и т.п. используется все-таки не size_t, а некий size_type, причем для каждого класса он определен внутри класса. В хелпе иногда помечено, что это unsigned integer type, а где-то прямо написано, что-то типа "можете считать это синонимом size_t".

В общем, вроде понятно. Но есть в этом какая-то неприятная зыбкость.
Можете рассказать что здесь и как?

нормального решения так и не придумали.

Нормального решения не нормальной задачи? )))

Хоть бы какую стандартную функцию сделали: типа «зафиксировано переполнение?».

Каким образом? :)

Тоже и к переполнению знаковых переменных.

Беззнаковые числа не переполняются, к ним применяется «арифметика по модулю степеней двойки» (модульная арифметика? o_O Не знаю как это перевести на русский).
А знаковые могут быть представлены не так, как Вы привыкли, плюс ко всему, если возникло переполнение, то скорее всего причина этому между монитором и креслом, а не в типе данных.

а где-то прямо написано, что-то типа «можете считать это синонимом size_t».

В исходниках контейнера. size_type не обязан быть size_t.

Я в процессорах не сильно волоку, но читал, что во многих процессорах есть флаг (бит) переноса. Т.е. если при выполнении машинной инструкции происходит как бы выход за пределы разрядной сетки, этот флаг выставляется в 1. Подробности гуглить не охота, но такой факт есть. Это во-первых.

Во-вторых, во многих языках/системах программирования вообще нет такого переполнения, как это понимается в C/C++. Есть +/-Inf, NaN, исключения в конце-концов. Т.е. RTS языка отлавливает эти ситуации на уровне процессора и предоставляет интерфейс, что бы на них реагировать.

но читал, что во многих процессорах есть флаг (бит) переноса. Т.е. если при выполнении машинной инструкции происходит как бы выход за пределы разрядной сетки, этот флаг выставляется в 1.

Не буду расписывать всё, просто поверь, что даже при наличии данного флага в регистре процессора, всё не так просто. Да и контролировать переполнение в большинстве случаев нет необходимости. И с умножением не всё так очевидно там. В общем, как с ассемблером познакомишься, узнаешь откуда растут корни.

во многих языках/системах программирования вообще нет такого переполнения, как это понимается в C/C++. Есть +/-Inf, NaN, исключения в конце-концов.

Это одна из причин их тормознутости. ))) В большинстве случаев нет никаких потребностей в контроле переполнений, любой подобный контроль приведет к накладным расходам. Если нужен контроль, без потери производительности (условно и не всегда), то можно сделать asm-вставку.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.