Как именно справляется 32-битная система Linux long long int
по сравнению с 64-битным Linux?
В моей 32-битной системе я использую C ++ обертка для типа данных MPFR; эта оболочка имеет конструктор, определенный для long int
но нет long long int
, Тем не менее, в 32-битной системе этот код просто работает:
long long int i=5LL;
mpreal myVar(i);
cout<< "this was constructed with a long long int:" <<myVar <<endl;
Как это возможно? 32-битный gcc просто как-то разыгрывает long long int
в скажем long int
для которого mpreal
тип данных делает есть конструктор? Если приведенный выше код выполняется на 64-битном Linux, то компилятор выдает ошибку о неоднозначности конструкции.
Я знаю, что некоторые люди скажут мне не использовать long long int
вообще на 64-битной, но, к сожалению, я использую другую библиотеку (odeint), где она встроена в код, для создания моего данного типа данных мультиточности таким образом, поэтому я не думаю, что могу что-то изменить.
Является long long int
точно так же, как long int
на 64-битной в любом случае? Потеряю ли я данные, если брошу на long int
? например если я сделаю свой собственный конструктор, как:
mpreal(const long long int u, mp_prec_t prec, mp_rnd_t mode)
{
mpfr_init2(mp,prec);
mpfr_set_si(mp, u, mode);
}
Я спросил об этом автора mpreal.h (полный ответ на http://www.holoborodko.com/pavel/mpfr/#comment-7444), во-первых, о создании нового конструктора для long long int
в системе 64x:
>Functions “mpfr_set_ui/si” should be fine.
>Basically constructor for “long long int” should be equivalent to “long int” one.
>GNU GCC system makes porting from x32 to x64 a little bit messy. It automatically
>upgrades integer types to x64 bits, which could easily break code being ported.
>The best workaround for GCC would be to use types with explicit number of bits:
>int32_t, int64_t from stdint.h. Then move from x32 to x64 would be painless.
>However neither authors of MPFR nor developers of numeric libraries follow this
>standard using “long long int”, “long int”, “intmax_t” all of which means different
>things on x32 and x64 in GCC world.
>There is some macro-logic in mpreal.h which tries to make things smooth:
>(a) for x32 builds we define additional constructors for int64_t (aka “long long int”
>or “intmax_t” )
>(b) for x64 builds we remove constructors for such type since “long int” is already
>64bit wide.
>Macro MPREAL_HAVE_INT64_SUPPORT plays only “suggestive” role, it is undefined
>automatically for x64 builds on GCC to avoid clash among integer types.
>The better way would be to detect bit resolution of all integer types at compile time
>(using macros or meta-magic similar to boost) and add suitable routines to mpreal
>class. This could easily grow to be more complex than mpreal itself :) .
>Maybe I will come up with better solution in future versions, any suggestions are
>welcome.
Поэтому я думаю, что сборка в моем конструкторе из OP исправит ситуацию, чтобы она работала нормально в системе x64, но ее нужно будет снова удалить, если вернуться к системе x32, иначе это вызовет конфликт. Причина в том, что MPREAL_HAVE_INT64_SUPPORT
макрос определяется на 32x и конструкторы для int64_t
(ака long long int
в 32x) получить определение, поэтому добавление еще одного такого конструктора вызовет конфликт; это также причина, по которой мой код только что сработал из коробки на 32 системе. В системе 64х MPREAL_HAVE_INT64_SUPPORT
макрос не определен и такие конструкторы удаляются, так как long int
ширина уже 64 бита, поэтому автору не нужно было long long int
конструктор.
Для размеров различных типов проверьте Стандарт C, long long
должен быть представлен как минимум 64 битами.
Чтобы увидеть, что компилятор действительно делает с вашим кодом, вы можете использовать, например, objdump -D
на двоичный файл (или промежуточный объектный файл).
На 32 битной арке ты будут потерять данные, если вы приведете из long long
в long
,
Насколько я понимаю, у компилятора могут возникнуть проблемы с решением, какой конструктор использовать (в принципе, не могу решить, использовать ли его ctor(int)
или же ctor(long int)
).
РЕДАКТИРОВАТЬ:
#include <stdint.h>
...
uint64_t x = 5;
mpreal myVar(i);
работает как c-tor(uint64_t)
определяется (или лучше сказать, однозначное совпадение может быть найдено) — потому что на 64-битной арке (unsigned) long int
эквивалентно uint64_t
(для glibc это фактически определено как таковое). Ошибка возникает из-за правил, которые компилятор использует при работе с перегруженными функциями. Стандарт C ++ 11/проект.
Вообще говоря, если вы хотите, чтобы ваш код переносился, вы должны использовать типы, определенные в inttypes.h
или же stdint.h
— то есть C99 — т.е. uintXX_t
а также intXX_t
, Эти типы гарантированно обеспечивают точную ширину, см. Ссылку на вики выше для получения дополнительной информации.