Commercial Products
Sep '09

The Secret of Object#to_s

posted by delano

There's something about Ruby that I've wanted to know for a long time: where does the hexadecimal value in #<Object:0x000001009e60f8> come from? Today I finally went looking for the answer.

When in doubt, look at the code

The documentation for Object#to_s tells us that the value is based on the object id: "Returns a string representing obj. The default to_s prints the object‘s class and an encoding of the object id."

Looking at the source code for to_s, we can see that it's using sprintf to create the hexadecimal value. From object.c:

/ Ruby 1.9 /
rb_sprintf("#<%s:%p>", cname, (void*)obj);

/ Ruby 1.8 / snprintf(RSTRING(str)->ptr, len+1, "#<%s:0x%lx>", cname, obj);

You can find this code in the Ruby source code in the file ruby-VERSION/object.c

Now, Ruby's sprintf doesn't support %p or %lx but it does support %x. However, there's obviously more to the story because the values still don't match up:

obj =
"#<%s:0x%x>" % [obj.class, obj.object_id]        # => #<Object:0x80813ff4>
obj.to_s                                         # => #<Object:0x101027fe8>

So what do we need to do to the object id to get the real hexadecimal value?

A tiny calculation

If we take a look at the hexadecimal values in plain-old decimal, the answer becomes obvious. Can you see it?

"0x80813ff4".hex                                 # => 2155954164
"0x101027fe8".hex                                # => 4311908328

All we have to do is double it!

And the answer is...

"#<%s:0x%x>" % [obj.class, obj.object_id.abs*2]  # => #<Object:0x101027fe8>

Note: I've created a tiny project called Hexoid to handle the minor formatting difference between Ruby 1.8 and 1.9.

I'm Delano Mandelbaum, the founder of Solutious Inc. I've worked for companies large and small and now I'm putting everything I've learned into building great tools. I recently launched a monitoring service called Stella.

You can also find me on:

-       Delano (

Solutious is a software company based in Montréal. We build testing and development tools that are both powerful and pleasant to use. All of our software is on GitHub.

This is our blog about performance, development, and getting stuff done.

-       Solutious