Id2sym&symbol.object_id
使用ruby-hacking-guide网站 ,我发现fixnum << 8 | 1
fixnum << 8 | 1
是任何fixnum的object_id。
我尝试过使用符号的类似方法。
#define ID2SYM(x) ((VALUE)(((long)(x))<<8|SYMBOL_FLAG))
当向左移8位时,
x
变为256的倍数,这意味着4的倍数。然后按位或(在这种情况下,它与添加相同)与0×0e
(十进制14)
我尝试过:a
( :a.object_id
= 175_976,在我的32位系统上):
- a的ASCII码是97。
- 97 << 8 = 24832
- 24832 | 14 = 24_846
所以它甚至不接近:a
对象id。
我检查了object_id
来源,发现了这个:
* sizeof(RVALUE) is * 20 if 32-bit, double is 4-byte aligned * 24 if 32-bit, double is 8-byte aligned * 40 if 64-bit */ if (SYMBOL_P(obj)) { return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
我得到~50万,这是不好的价值。
那么我错过了什么? 如何计算符号的object_id?
您从符号object_id
计算的ID
值不直接表示该符号的字符串内容。 它是Ruby维护包含字符串的表的索引。 当你在Ruby中使用一个符号时,如果在当前进程中之前没有使用过该符号,它将被赋予符号表中下一个空闲槽的ID
值。
这意味着给定的符号并不总是具有相同的ID
值。 与Ruby进程符号关联的ID
值将取决于它们的创建顺序。
您可以通过启动新的Ruby进程,创建新符号并查看其object_id
,然后使用不同的符号名称重复来看到这一点。 在两种情况下, object_id
应该相同,因为它将引用符号表中的下一个空闲点。 你需要小心这样做,因为Ruby自己定义了很多符号,所以如果你使用其中一个符号,你会得到不同的结果。
例如, irb
会话:
2.1.0 :001 > Symbol.all_symbols.find {|sym| sym.to_s == 'matt' } => nil 2.1.0 :002 > :matt.object_id => 542248
而另一个:
2.1.0 :001 > Symbol.all_symbols.find {|sym| sym.to_s == 'banana' } => nil 2.1.0 :002 > :banana.object_id => 542248
这里我们首先检查我们要使用的名称是否已经作为符号存在,然后我们创建符号并查看其object_id
。 在这两种情况下,它都是相同的542248
,对应于ID
2118,即使它们具有不同的名称(这些值在不同的系统或Ruby版本上可能不同)。