Подозрительное поведение shl

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

Т.е. 1000000000000000000000000000000000000000000000000000000000000000 на 64-битной системе и 0000000000000000000000000000000010000000000000000000000000000000 на 32-битной?
iskander
энтузиаст
Сообщения: 627
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

Kemet писал(а):результат будет зависеть от битности системы

x86: 1111111111111111111111111111111110000000000000000000000000000000
x86_64: 1111111111111111111111111111111110000000000000000000000000000000
:?
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

И добавлю ARMv6: 0000000000000000000000000000000000000000000000000000000000000000 :)
Kemet
постоялец
Сообщения: 241
Зарегистрирован: 10.02.2010 18:28:32
Откуда: Временно оккупированная территория
Контактная информация:

Сообщение Kemet »

А если

Код: Выделить всё

  function SixtyThree: UInt64;
  begin
    SixtyThree := 63;
  end;
var
  U: UInt64;
begin
  U := UInt64(1) shl SixtyThree;
  Writeln(BinStr(U, 64));
end.

Вообще, смешивать знаковые и беззнаковые в одном выражении это моветон
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

С такой явной подсказкой оно работает как надо. А что, константа 1 -- это знаковое?

Проблема в том, что выражения бывают довольно сложные, в которых непонятно знаковое ли там число или нет. Например, следующие две программы у меня выдают разные результаты:

Код: Выделить всё

  function SixtyThree: UInt64;
  begin
    SixtyThree := 63;
  end;
var
  U: UInt64;
begin
  U := Ord(True) shl SixtyThree;
  Writeln(BinStr(U, 64));
end.

Код: Выделить всё

type
  E = (Zero = 0, One = 1);
  function SixtyThree: UInt64;
  begin
    SixtyThree := 63;
  end;
var
  U: UInt64;
begin
  U := Ord(One) shl SixtyThree;
  Writeln(BinStr(U, 64));
end.

Ни та, ни другая не выдают того, что ожидает наивный программист (!)
SSerge
энтузиаст
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Сообщение SSerge »

iskander писал(а):PS

RAD Studio 10.3 Rio писал(а):
Note that the value of y is interpreted modulo the size of the type of x.
Thus for example, if x is an integer, x shl 40 is interpreted as x shl 8 because an integer is 32 bits and 40 mod 32 is 8.


Вот кстати, хреново, что сие описание есть в Ras Studio, но поведение нисколько не документировано в документации fpc. Если оно действительно так.
Kemet
постоялец
Сообщения: 241
Зарегистрирован: 10.02.2010 18:28:32
Откуда: Временно оккупированная территория
Контактная информация:

Сообщение Kemet »

Дож писал(а):А что, константа 1 -- это знаковое?
А какое? ))) Компилятор же не знает чего об этом думает программист, поэтому вынужден следовать определенному соглашению, например, что все числовые константы это знаковое целое.

Добавлено спустя 4 минуты 51 секунду:
Дож писал(а):Ни та, ни другая не выдают того, что ожидает наивный программист (!)

Насколько я помню, результат функции ORD - целочисленный, то есть знаковое целое
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

Тогда почему разные результаты? И там, и там Ord :)
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Kemet писал(а): потому что константное выражение, а оно, вроде как, считается в 64 бит всегда

Практика показывает, что это совсем не так. Для нецелых чисел 32-ух битный компилятор засовывает константы в Extended, а 64-ехбитный - в Double. Для целых чисел подбирается тип, в который влазиет число. Но если число будет больше чем 32 бита, то компилятор всё равно тупо суёт его в 32 бита. В этом отношении очень легко нарваться на ошибку, которую будешь искать очень долго и, возможно, безуспешно... ;-)
Kemet
постоялец
Сообщения: 241
Зарегистрирован: 10.02.2010 18:28:32
Откуда: Временно оккупированная территория
Контактная информация:

Сообщение Kemet »

Дож писал(а):Тогда почему разные результаты? И там, и там Ord :)
Хз, возможно из-за того, что E это пользовательский тип, фрипаскаль обрабатывает выражение как-то иначе, нужно с Дельфи сравнить

Добавлено спустя 4 минуты 26 секунд:
Видимо, Ord( True ), в итоге преобразуется к Int64, а Ord( One ) остаётся Integer
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Kemet
Неправильно Вам про целые сказал. :-) Целые константы компилятор всегда пытается засунуть в минимально возможный тип, я только не знаю, как он там ориентируется в знаково-беззнаковых типах...
Kemet
постоялец
Сообщения: 241
Зарегистрирован: 10.02.2010 18:28:32
Откуда: Временно оккупированная территория
Контактная информация:

Сообщение Kemet »

Тынц
FPC evaluates constant expressions always using 64 bit arithmetic in all modes, and has done so since the moment it supported 64 bit arithmetic. If you use WriteLn(int64(i) shr 32);, you'll also get 0 in the second case. Changing that would break backwards FPC compatibility. It also wouldn't surprise me if Delphi XE3 would give the same output as FPC.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Kemet

Код: Выделить всё

Const
  c1 = 22;
  c2 = 33.33;
  c3 = 2200000000;
  c4 = 9200000000000000;
Begin
  WriteLn(sizeof(c1));
  WriteLn(sizeof(c2));
  WriteLn(sizeof(c3));
  WriteLn(sizeof(c4));
End.

Тынц... ;-)
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Kemet
постоялец
Сообщения: 241
Зарегистрирован: 10.02.2010 18:28:32
Откуда: Временно оккупированная территория
Контактная информация:

Сообщение Kemet »

Так речь идёт о константных выражениях, а не о том, сколько места занимает объявленная константа.
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3067
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

Эта фигня с целыми в разной битности компилятора проявляется много где. Например, сталкивался, что при попытки конвертировать слишком большое символьное представление в integer в 32х програме дает правльно сообщение об ошибке. А в 64х программе сообщения об ошибке нет, но результат мусорный.
Ответить