我对某些 ruby 行为感到困惑。看下面的代码:
[127].pack("C") == "\x7f" # => true
这是有道理的。现在:
[128].pack("C") # => "\x80"
"\x80" # => "\x80"
[128].pack("C") == "\x80" # => false
pack option "C"代表
8-bit unsigned (unsigned char)
,应该可以存储128
的值。而且两个字符串都打印相同的东西,所以为什么它们不相等?这与编码内容有关吗?我使用的是ruby 2.0.0p247。
最佳答案
这是错误的,因为编码不同:
[128].pack("C").encoding
#=> #<Encoding:ASCII-8BIT>
"\x80".encoding
#=> #<Encoding:UTF-8>
(使用
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux]
)在ruby 2.0中,字符串的默认编码为UTF-8,但是
pack
以某种方式返回ASCII 8位编码的字符串。为什么
[127].pack('C') == "\x79"
是true?但是,
[127].pack('C') == "\x79"
是true
,因为对于代码点0
到127
,ASCII和UTF-8不会不同。这是通过ruby的字符串比较来考虑的(请看the rubinius source code):def ==(other)
[...]
return false unless @num_bytes == other.bytesize
return false unless Encoding.compatible?(self, other)
return @data.compare_bytes(other.__data__, @num_bytes, other.bytesize) == 0
end
mri c-source是相似的,但是更难理解。
我们观察到,比较检查了兼容的编码。让我们尝试一下:
Encoding.compatible?([127].pack("C"), "\x79") #=> #<Encoding:ASCII-8BIT>
Encoding.compatible?([128].pack("C"), "\x80") #=> nil
我们看到,从代码点128开始,即使两个字符串都由相同的字节组成,比较也返回
false
。