Perl 十六进制数的负表示总是符号扩展为 8 个字节
Negative representation of Perl hex number is always sign-extended to 8 bytes
我在 Perl 中使用 sprintf
将十进制数转换为它们的十六进制数,如:
my $positive = sprintf("X'%02X'", 1); # X'01'
my $negative = sprintf("X'%02X'", -1); # X'FFFFFFFFFFFFFFFF'
为什么负数总是被符号扩展为数字的 8 字节表示,即使 sprintf
中指定的精度更小?
有没有办法避免这种情况,这样我就不必每次都对值进行子字符串化?即使我删除 0
,也会出现相同的结果,如:sprintf("X'%2X'", -1)
.
好吧,%x
特别需要一个无符号整数,所以当你给它一个有符号整数的位模式时,它会将所有这些位都视为一个无符号位。输出的长度可能取决于你的编译器生成的数字有多大(尽管我猜现在大多数现代事物都是一样的)。 Perl 将它的大部分数字存储为双精度数,所以这就是数字的大小。它是 Perl 公开底层架构的少数几个地方之一。
这意味着你需要自己处理符号并使用数字的绝对值:
sprintf( "%s%2x", ($n < 0 ? '-' : ''), abs($n) );
至于 sprintf 字段说明符,您没有在那里指定精度。那是最小宽度。 %f
和 %g
说明符可能具有最大小数位数,但整个字符串仍然可以溢出。
但是,事实证明你的问题不一样。您希望从 -128 到 127 的值是它们的有符号整数形式。所以,-1 得到 FF
。您需要添加一点才能做到这一点。
my $s = sprintf( "%2x", $n );
$s = substr( $s, -2 ) if $n < 0;
我在 Perl 中使用 sprintf
将十进制数转换为它们的十六进制数,如:
my $positive = sprintf("X'%02X'", 1); # X'01'
my $negative = sprintf("X'%02X'", -1); # X'FFFFFFFFFFFFFFFF'
为什么负数总是被符号扩展为数字的 8 字节表示,即使 sprintf
中指定的精度更小?
有没有办法避免这种情况,这样我就不必每次都对值进行子字符串化?即使我删除 0
,也会出现相同的结果,如:sprintf("X'%2X'", -1)
.
好吧,%x
特别需要一个无符号整数,所以当你给它一个有符号整数的位模式时,它会将所有这些位都视为一个无符号位。输出的长度可能取决于你的编译器生成的数字有多大(尽管我猜现在大多数现代事物都是一样的)。 Perl 将它的大部分数字存储为双精度数,所以这就是数字的大小。它是 Perl 公开底层架构的少数几个地方之一。
这意味着你需要自己处理符号并使用数字的绝对值:
sprintf( "%s%2x", ($n < 0 ? '-' : ''), abs($n) );
至于 sprintf 字段说明符,您没有在那里指定精度。那是最小宽度。 %f
和 %g
说明符可能具有最大小数位数,但整个字符串仍然可以溢出。
但是,事实证明你的问题不一样。您希望从 -128 到 127 的值是它们的有符号整数形式。所以,-1 得到 FF
。您需要添加一点才能做到这一点。
my $s = sprintf( "%2x", $n );
$s = substr( $s, -2 ) if $n < 0;