Долгое длинное целое на машинах на 32 бита

очень простой вопрос, я считал, что GCC поддерживает длинный тип длинного целого. Но как может сделать математические операции с ним, когда ЦП 32 бита шириной только?

14
задан dty 18 June 2010 в 19:29
поделиться

5 ответов

Компилятор будет синтезировать математические операции (или использовать вызовы функций), которые используют более одной инструкции процессора для выполнения операции. Например, операция сложения будет складывать компоненты низкого порядка (младшие слова) значений long long, а затем возьмет перенос этой операции и передаст его в операцию сложения слов старшего порядка long long.

Таким образом, следующий код на языке Си:

long long a;
long long b;
long long c;

// ...
c = a + b;

может быть представлен последовательностью команд, которая выглядит примерно так:

mov eax, [a.low]   ; add the low order words
add eax, [b.low]

mov edx, [a.high]  ; add the high order words, 
adc edx, [b.high]  ; including the carry 

mov [c.low], eax
mov [c.high], edx

И если вы на секунду задумаетесь, компиляторы для 8- и 16-битных систем должны были делать подобные вещи для 16- и/или 32-битных значений задолго до появления long long.

22
ответ дан 1 December 2019 в 07:27
поделиться

Скорее всего, как класс, а не изначально. таким же образом любой компилятор может / может поддерживать любой большой набор чисел.

1
ответ дан 1 December 2019 в 07:27
поделиться

Утверждение, что архитектура 32-битная (или 64-битная, или что-то еще), обычно является лишь приближением того, на что способен процессор. Обычно вы ссылаетесь только на ширину указателей с этим числом, арифметика может быть совсем другой. Например, архитектура x86 имеет 32-битные указатели, большая часть арифметических операций выполняется в 32-битных регистрах, но она также имеет встроенную поддержку некоторых базовых 64-битных операций.

Также не должно создаваться впечатление, что стандартные целочисленные типы имеют некоторую заданную ширину. В частности, long long - это не менее 64 бит, но может быть шире. Используйте typedefs int32_t, int64_t, если вы хотите быть уверенным в переносимости ширины.

Если вы хотите знать, что gcc (или любой другой компилятор) делает с long long, вам нужно изучить спецификацию для вашей конкретной целевой платформы.

2
ответ дан 1 December 2019 в 07:27
поделиться

Достаточно просто скомпилировать и проверить, доступна ли у вас 32-битная система. gcc имеет флаг -S , который включает вывод на языке ассемблера. Вот что он дает на моем 32-битном Intel:

// read two long longs from stack into eax:edx and ecx:ebx
movl    32(%esp), %eax
movl    36(%esp), %edx
movl    24(%esp), %ecx
movl    28(%esp), %ebx
// a+b
addl    %ecx, %eax
adcl    %ebx, %edx
// a-b
subl    %ecx, %eax
sbbl    %ebx, %edx
// etc
2
ответ дан 1 December 2019 в 07:27
поделиться

Внутри тип представлен словом high и словом low, например:

struct long
{
  int32 highWord;
  uint32_t lowWord;
}

Компилятору нужно знать, 32-битная или 64-битная среда, и затем выбрать правильное представление числа - если 64-битная, это может быть сделано нативно, если 32-битная, компилятор должен позаботиться о математике между словом high/low.

Если вы заглянете в math.h, то сможете увидеть функции, используемые для этого, и использовать их самостоятельно. Кроме того, помните о разнице между little-endian и big-endian (см. wiki), использование зависит от операционной системы.

9
ответ дан 1 December 2019 в 07:27
поделиться