gpt4 book ai didi

delphi - 对于非寄存器大小的操作数,shl 和 shr 的行为是什么?

转载 作者:行者123 更新时间:2023-12-03 14:38:23 24 4
gpt4 key购买 nike

这个问题的灵感来自于我尝试回答另一个问题:Converting decimal/integer to binary - how and why it works the way it does?

唯一documentation对于我能找到的按位移位运算符说:

The operations x shl y and x shr y shift the value of x to the left or right by y bits, which (if x is an unsigned integer) is equivalent to multiplying or dividing x by 2^y; the result is of the same type as x. For example, if N stores the value 01101 (decimal 13), then N shl 1 returns 11010 (decimal 26). 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.

考虑这个程序:

{$APPTYPE CONSOLE}
program BitwiseShift;
var
u8: Byte;
u16: Word;
u32: LongWord;
u64: UInt64;
begin
u8 := $ff;
Writeln((u8 shl 7) shr 7);
// expects: 1 actual: 255

u16 := $ffff;
Writeln((u16 shl 15) shr 15);
// expects: 1 actual: 65535

u32 := $ffffffff;
Writeln((u32 shl 31) shr 31);
// expects: 1 actual: 1

u64 := $ffffffffffffffff;
Writeln((u64 shl 63) shr 63);
// expects: 1 actual: 1
end.

我已经使用 XE3 和 XE5(针对 32 位和 64 位 Windows 编译器)运行此程序,并且输出是一致的,如上面代码中所述。

我预计 (u8 shl 7) shr 7 将完全在 8 位类型的上下文中进行计算。因此,当位移位超出该 8 位类型的末尾时,这些位就会丢失。

我的问题是为什么程序会这样做。

<小时/>

有趣的是,我将程序翻译为 C++,并在 64 位 mingw 4.6.3 上获得了相同的输出。

#include <cstdint>
#include <iostream>

int main()
{
uint8_t u8 = 0xff;
std::cout << ((u8 << 7) >> 7) << std::endl;

uint16_t u16 = 0xffff;
std::cout << ((u16 << 15) >> 15) << std::endl;

uint32_t u32 = 0xffffffff;
std::cout << ((u32 << 31) >> 31) << std::endl;

uint64_t u64 = 0xffffffffffffffff;
std::cout << ((u64 << 63) >> 63) << std::endl;
}

最佳答案

原因是type promotion :

One special case of implicit type conversion is type promotion, where the compiler automatically expands the binary representation of objects of integer or floating-point types. Promotions are commonly used with types smaller than the native type of the target platform's ALU prior to arithmetic and logical operations in order to make such operations possible, or more efficient if the ALU can work with more than one type. C and C++ perform such promotion for objects of boolean, character, wide character, enumeration, and short integer types which are promoted to int, and for objects of type float, which are promoted to double. Unlike some other type conversions, promotions never lose precision or modify the value stored in the object.

所以在下面的代码中

var
u8: Byte;

begin
u8 := $ff;
Writeln((u8 shl 7) shr 7);
..

u8 值在 shl 之前提升为 32 值;要修复结果,您需要显式类型转换:

  Writeln(Byte(u8 shl 7) shr 7);
<小时/>

C++ 标准,第 4.5 节积分促销:

An rvalue of type char, signed char, unsigned char, short int, or unsigned short int can be converted to an rvalue of type int if int can represent all the values of the source type; otherwise, the source rvalue can be converted to an rvalue of type unsigned int.

<小时/>

为了检查 Delphi 在类型提升方面是否遵循相同的约定,我编写了以下应用程序:

var
u8: Byte;
u16: Word;
u32: LongWord;

procedure Test(Value: Integer); overload;
begin
Writeln('Integer');
end;

procedure Test(Value: Cardinal); overload;
begin
Writeln('Cardinal');
end;

begin
u8 := $ff;
Test(u8); // 'Integer'
u16 := $ffff;
Test(u16); // 'Integer'
u32 := $ffffffff;
Test(u32); // 'Cardinal'
Readln;
end.

所以我相信Delphi和C++在这里应该没有区别。

关于delphi - 对于非寄存器大小的操作数,shl 和 shr 的行为是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21362455/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com