size_t в беззнаковое целое (из функции API)

Я использую Oracle API для доступа к базе данных, и этот API имеет функцию readBuffer(char * buffer, unsigned int size);, в которую я не могу вносить никаких изменений.

У меня есть класс, который использует этот API, и сигнатура моей функции в настоящее время принимает std::string и unsigned int для размера, проблема в том, что когда я передаю std::string.size() аргументу размера моей функции, я получаю предупреждение от моего компилятора о том, что преобразование с size_t по unsigned int может привести к потере данных.

Мне интересно, есть ли правильный способ преобразовать size_t в unsigned int, чтобы я мог передать его в свой API и не получить предупреждение от компилятора?

Я понимаю цель size_t, и поиск в Google для этого преобразования дает много результатов, в которых говорится: «измените функцию, чтобы она принимала аргумент size_t», но в этом случае я НЕ МОГУ изменить подпись своего API.

Какие-либо предложения?


person Tony The Lion    schedule 19.04.2011    source источник
comment
size_t на самом деле не что иное, как используемый тип int. Проблема в том, что длина size_t точно не определена, если ваша система определяет, что она имеет больше битов, чем обычное целое число без знака, вы ничего не можете сделать, чтобы избежать возможной потери данных. Предупреждение также появляется при явном кастинге?   -  person Chris    schedule 19.04.2011


Ответы (5)


Да, напишите вспомогательную функцию, которая будет проверять правильность такого преобразования и выдавать исключение в противном случае. Что-то типа:

unsigned int convert( size_t what )
{
    if( what > UINT_MAX ) {
       throw SomeReasonableException();
    }
    return static_cast<unsigned int>( what );
}
person sharptooth    schedule 19.04.2011
comment
Да, мне нравится эта идея. Практически маловероятно, что размер строки превысит 32 бита (4 ГБ), но это хорошая практика. - person Diego Sevilla; 19.04.2011
comment
boost::numeric_cast делает это более или менее. - person Steve Jessop; 19.04.2011

Что ж, сделай static_cast<unsigned int>(mystring.size()).

Причина в том, что std::size_t обычно имеет размер указателя, но есть 64-битные платформы, на которых int по-прежнему составляет 32 бита. В этом случае единственной причиной потери данных может быть длина рассматриваемой строки более 2^32 байт.

Если вы знаете, что этого не произойдет, поставьте где-нибудь assert, чтобы поймать этот случай, и static_cast, чтобы компилятор замолчал.

person Alexander Gessler    schedule 19.04.2011

static_cast<unsigned int>(str.size());

Если вы хотите быть параноиком:

if (static_cast<unsigned int>(str.size()) != str.size()) 
  throw ...
person Erik    schedule 19.04.2011

Вы можете принудительно преобразовать с помощью

static_cast<unsigned int>(your_variable)

построить. Конечно, правильно было бы, чтобы API принимал size_t...

person Diego Sevilla    schedule 19.04.2011

Риск здесь заключается в том, что size_t может быть больше, чем (unsigned) int, и, следовательно, вы не можете безопасно конвертировать, если это так.

Например, возможно, что int — это 32 бита, а size_t — 64 бита. Я не знаю такой системы/конфигурации навскидку, но это может произойти.

Для большинства «разумных» систем обе будут как минимум 32-битными, и одна строка размером 4 ГБ по-прежнему (возможно) маловероятна.

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

person unwind    schedule 19.04.2011
comment
Я не знаю такой системы/конфигурации навскидку - 64-битная винда, 64-битный линукс. - person Steve Jessop; 19.04.2011