Как избежать проблем с типами size_t и int в 64-битных сборках C++?

Сегодня я впервые сделал 64-битную сборку своего проекта. В основном он скомпилировался, скомпоновался и работал нормально, за исключением предупреждений о несовместимости между новым 64-битным типом size_t и простым типом int. В основном это происходит в таких ситуациях в моем коде:

void func(std::vector<Something> &vec)
{
    int n = vec.size();
    for (int i=0; i < n; i++)
    {
        ....vec[i]....
    }
}

Это довольно легко исправить, и я читал статью, в которой говорилось, что в качестве индексов циклов лучше использовать size_t или ptrdif_t. Но что я могу сделать в такой ситуации?

void outsideLibraryFunc(int n);

void func(std::vector<Something> &vec)
{
    int n = vec.size();
    outsideLibraryFunc(n);
}

Я не могу изменить объявление функции внешней библиотеки, которая ожидает аргумент типа int, и мне нужно передать ей количество элементов вектора. Что я могу сделать, кроме отключения предупреждений компилятора?


person neuviemeporte    schedule 30.09.2010    source источник
comment
+1 к вопросу: я не знал, что size_t != unsigned int   -  person pm100    schedule 30.09.2010
comment
@pm100 Это может быть, и в большинстве 32-битных систем это так, но это не обязательно. В частности, в 64-битных системах, использующих соглашения LP64 или LLP64 (большинство современных 64-битных систем), он имеет тенденцию быть больше, чем unsigned int.   -  person Tyler McHenry    schedule 30.09.2010
comment
ssize_t иногда доступен для подписанного size_t   -  person user318904    schedule 01.10.2010


Ответы (2)


Сделайте явное приведение к int, например.

void outsideLibraryFunc(int n);

void func(std::vector<Something> &vec)
{
    outsideLibraryFunc(static_cast<int>(vec.size()));
}

Это не устраняет потенциальных проблем с преобразованием size_t в int, но сообщает компилятору, что вы выполняете преобразование намеренно, и не предупреждает вас об этом.

person Tyler McHenry    schedule 30.09.2010
comment
+1. Большим преимуществом является то, что при чтении кода вы видите приведение, которое в противном случае было бы неявным, и, зная, что компилятор не может иметь, вы можете проверить, имеет ли это смысл или нет. Как в примере: хотя компилятор не может гарантировать, что значение, возвращаемое функцией типа size_t, будет соответствовать 32-битному целому числу, вы можете вручную проверить, имеет ли оно смысл или нет. - person David Rodríguez - dribeas; 01.10.2010

Бросить? Серьезно, если вы не можете изменить внешнюю библиотеку, вы мало что можете сделать. Для дополнительной безопасности проверьте переполнение.

person user318904    schedule 30.09.2010
comment
+1 за проверку переполнения (хотя у вас редко бывает более 2 миллиардов объектов) - person Viktor Sehr; 30.09.2010
comment
Как проверить переполнение? Я немного припоминаю бит переполнения в EFLAGS, но как мне получить к нему доступ на C-образе? - person neuviemeporte; 30.09.2010
comment
@neuviemeporte: if (vec.size() › INT_MAX) { /* error /} else { / (int) cast будет работать */ }. Но, как сказал Виктор, проверка может быть излишней... - person Michael Burr; 30.09.2010
comment
Да, проверка переполнения почти наверняка избыточна. Просто кое-что, что следует учитывать при сужении бросков. Проверка флагов ЦП после операции не будет переносимой. И, как писал Майкл: просто найдите или определите максимальное целое число платформы, сравните. Но на самом деле, если у вас есть вектор с таким количеством элементов, что он переполнит целое число, у вас, вероятно, не останется памяти, и вам не придется беспокоиться об этих вещах. - person user318904; 01.10.2010