long long int на 32-битном Linux против 64-битного Linux и MPFR

Как именно справляется 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);
}

0

Решение

Я спросил об этом автора 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 конструктор.

1

Другие решения

  • Для размеров различных типов проверьте Стандарт 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, Эти типы гарантированно обеспечивают точную ширину, см. Ссылку на вики выше для получения дополнительной информации.

0

По вопросам рекламы [email protected]