Perl Weekly Challenge 108: Locate Memory

by Abigail

Challenge

Write a script to declare a variable or constant and print its location in the memory.

Solution

This is a challenge which can only be solved in some languages. Many, if not most, hide the actual memory locations from the user.

Perl

There's not much to it. The \ operator returns a reference to its argument. And a reference in numeric context is the memory location of the reference.

say+0+\+0

Since +0 is a constant, \+0 is a reference to it. If its an argument of the addition operator (+), it's put in numeric context, and we get memory address. Adding +0 to it is a no-op. So +0+\+0 is the memory address of the constant +0. Which we print with say.

Find the full program on GitHub.

C

In C, the & operator returns a pointer to its argument; and a pointer is basically a memory location. We can print this straight away using the %p specifier for printf, however, this would print the address in hex format.

To use the same format as the output for our solutions in different languages, we cast the pointer to a long long, and print this.

int main (void) {
    int i;
    printf ("%lld\n", (long long) &i);
    return (0);
}

Find the full program on GitHub.

Fortran

In Fortran, the loc function returns the memory address of a variable:

program ch1
    implicit none
    integer :: i
    print *, loc(i)
end

Find the full program on GitHub.

Go

Like C, in Go, & returns a references to its argument, And you can just print that as a number:

func main () {
    x := 0
    fmt . Printf ("%d\n", &x)
}

Find the full program on GitHub.

Pascal

Pascal has pointers, but they aren't addresses in the sense they are in C. Depending on the flavour of Pascal, you may, or may not be able to get the memory location. We use the Free Pascal compiler, which does have a way to extract the address of a pointer.

The function addr takes a pointer as argument, and returns a pointer to a Word containing a memory address. The latter pointer can be dereferenced and printed.

var i: Integer;
    p: ^Integer;
    w: ^Word;

begin
    p := @i;
    w := addr (p);
    writeln (w^);
end.

Find the full program on GitHub.

Python

The id function returns the identify of an object, which is guaranteed to be unique. Due to an implementation detail, this is the memory address.

print (id (0))

Find the full program on GitHub.

R

In R, we have to work hard! We even have to work much harder than C.

x <- 0
cat (sprintf ("%.0f\n",
         as.numeric (
             paste0 ("0x", 
                 substring (
                     sub (" .*$", "",
                          capture.output (.Internal (inspect (x)))), 2)))))

We start off with .Internal (inspect (x)) write a bunch of information to standard output. This information looks like:

@7fc083998d20 14 REALSXP g0c1 [REF(3)] (len=1, tl=0) 0

The memory address starts right after the leading @. Since we want to extract just the memory address, and remove the rest, we want to capture what would normally be written to standard out. This is what capture.output does — it returns what otherwise would have been written to standard output.

We then remove everything from the first space onwards, using sub. This takes a pattern (" .*$"), a replacement ("" — the empty string), and a string to act upon (the result of capture.output).

Next step is to get rid of the leading @, by using substring.

We're now have the memory address, but as a string of hex digits. To turn this into a number, we first prepend 0x using paste0 and then turn it into a number with as.numeric. We then turn it back in to a string, but this time as a decimal number using sprintf.

Finally, we print the memory address using cat.

Find the full program on GitHub.

Ruby

In Ruby, object_id returns a unique id. For objects which aren't nil, true, false, Fixnums, Symbols, this returned number has a simple relation to the memory location of the object.

puts (Object . new . object_id << 1)

Find the full program on GitHub.


Please leave any comments as a GitHub issue.