Здравствуйте, Vamp, Вы писали:
V>В общем-то, есть довольно много материалов, посвященных проблемам, связанными с беззнаковыми целыми. Как правило, рассматриваются проблемы производительности или баги. Классический пример проблемы производительности выглядит так:
V>
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>}
V>
V>Данный код предполагает, что расстояние между началом и концом уменьшается в 32 бита, и в рамках этого предположения работает отлично. Если заменить тип управляющей переменной на unsigned int, скорость кода заметно уменьшится. Связано это с тем, что компилятору придется контролировать переполнение на каждой операции (как правило, путем засовывания числа в отдельный короткий регистр), так как беззнаковые целые разрешают переполнение. Классическая рекомендация — использовать знаковое целое.
Ноги у приведенной проблемы растут из за того что для адресных манипуляций используется слишком маленький тип. Правила расширения знаковых от 32 до 64бит дают такой эффект, что компилятору не приходится контролировать размер. Для без-знаковых — такого эффекта нет и компилятору приходится это делать вручную. Если этот код загнать на платформу, в которой размер int равен размеру указателя — беззнаковый вариант будет, как минимум, не хуже. А обычно он чуть-чуть лучше.
V>Очевидно, что проблему можно решить и более правильно — путем использования уместного типа, std::ptrdiff_t. Ирония заключается в том, что ptrdiff_t — знаковый тип.
Очевидно, что проблему можно решить и более правильно — путем использования уместного типа, std::size_t. Ирония заключается в том, что size_t — без-знаковый тип.
В общем, эта часть ответа не защитана.