# [C (gcc)], <s>18</s> 17 bytes

<!-- language: lang-c -->

<pre><code>f(){puts('@&#2;C');}
</code></pre>

Note that there's an STX byte (**0x02**) between `@` and `C`.

[Try it online!]

### Portability

This has been tested with gcc 6.3.1 and clang 3.9.1 on Fedora 25, gcc 4.8.4 on Ubuntu 14.04.4, and gcc 4.8.3 on openSUSE 13.2, where it prints the following output.

<pre><code>inux-x86-64.so.2

</code></pre>

I expect this to produce the same output with all versions of gcc, as long as it compiles to an executable of the following type.

    ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2

Different platforms will require a different memory address and possibly a different order for the bytes in the multi-character character constant.

For example, replacing `@\2C` with `@\2\4` prints `exec/ld-elf.so.1` and a newline on FreeBSD 11 with clang 3.8.0.

### Offline verification

    $ printf "%b\n" "f(){puts('@\2C');}main(){f();}" > quine.c
    $ gcc -w -o quine quine.c
    $ ./quine
    inux-x86-64.so.2
    $ ./quine | wc -c
    17

### How it works

By default, ld uses **0x400000** as the base address of the text segment, meaning that we can find the ELF's content starting at memory address **0x400000**.

The first 640 bytes of the ELF are largely independent of the actual source code. For example, if the declaration of **f** is followed by `main(){f();}` and nothing else, they look as follows.

    00000000: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  .ELF............
    00000010: 02 00 3e 00 01 00 00 00 00 04 40 00 00 00 00 00  ..>.......@.....
    00000020: 40 00 00 00 00 00 00 00 e8 19 00 00 00 00 00 00  @...............
    00000030: 00 00 00 00 40 00 38 00 09 00 40 00 1e 00 1b 00  ....@.8...@.....
    00000040: 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00  ........@.......
    00000050: 40 00 40 00 00 00 00 00 40 00 40 00 00 00 00 00  @.@.....@.@.....
    00000060: f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00  ................
    00000070: 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00  ................
    00000080: 38 02 00 00 00 00 00 00 38 02 40 00 00 00 00 00  8.......8.@.....
    00000090: 38 02 40 00 00 00 00 00 1c 00 00 00 00 00 00 00  8.@.............
    000000a0: 1c 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
    000000b0: 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00  ................
    000000c0: 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00  ..@.......@.....
    000000d0: 04 07 00 00 00 00 00 00 04 07 00 00 00 00 00 00  ................
    000000e0: 00 00 20 00 00 00 00 00 01 00 00 00 06 00 00 00  .. .............
    000000f0: 08 0e 00 00 00 00 00 00 08 0e 60 00 00 00 00 00  ..........`.....
    00000100: 08 0e 60 00 00 00 00 00 1c 02 00 00 00 00 00 00  ..`.............
    00000110: 20 02 00 00 00 00 00 00 00 00 20 00 00 00 00 00   ......... .....
    00000120: 02 00 00 00 06 00 00 00 20 0e 00 00 00 00 00 00  ........ .......
    00000130: 20 0e 60 00 00 00 00 00 20 0e 60 00 00 00 00 00   .`..... .`.....
    00000140: d0 01 00 00 00 00 00 00 d0 01 00 00 00 00 00 00  ................
    00000150: 08 00 00 00 00 00 00 00 04 00 00 00 04 00 00 00  ................
    00000160: 54 02 00 00 00 00 00 00 54 02 40 00 00 00 00 00  T.......T.@.....
    00000170: 54 02 40 00 00 00 00 00 44 00 00 00 00 00 00 00  T.@.....D.......
    00000180: 44 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00  D...............
    00000190: 50 e5 74 64 04 00 00 00 b0 05 00 00 00 00 00 00  P.td............
    000001a0: b0 05 40 00 00 00 00 00 b0 05 40 00 00 00 00 00  ..@.......@.....
    000001b0: 3c 00 00 00 00 00 00 00 3c 00 00 00 00 00 00 00  <.......<.......
    000001c0: 04 00 00 00 00 00 00 00 51 e5 74 64 06 00 00 00  ........Q.td....
    000001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    000001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    000001f0: 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00  ................
    00000200: 52 e5 74 64 04 00 00 00 08 0e 00 00 00 00 00 00  R.td............
    00000210: 08 0e 60 00 00 00 00 00 08 0e 60 00 00 00 00 00  ..`.......`.....
    00000220: f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00  ................
    00000230: 01 00 00 00 00 00 00 00 2f 6c 69 62 36 34 2f 6c  ......../lib64/l
    00000240: 64 2d 6c 69 6e 75 78 2d 78 38 36 2d 36 34 2e 73  d-linux-x86-64.s
    00000250: 6f 2e 32 00 04 00 00 00 10 00 00 00 01 00 00 00  o.2.............
    00000260: 47 4e 55 00 00 00 00 00 02 00 00 00 06 00 00 00  GNU.............
    00000270: 20 00 00 00 04 00 00 00 14 00 00 00 03 00 00 00   ...............

Using, e.g., `main(int c, char**v){f();}` instead changes some bytes, but not the offset of the string `/lib64/ld-linux-x86-64.so.2`, which we'll use to produce output.

The offset of said string is **0x238** and it is 27 bytes long. We only want to print 17 bytes (and the last one will be a newline if we use `puts`), so we add **11** to the offset to get **0x243**, the offset of `inux-x86-64.so.2`. Adding **0x400000** and **0x243** gives **0x400243**, the memory location of `inux-x86-64.so.2`.

To obtain this memory address, we can use multi-character character constants, which exhibit implementation-defined behavior. **0x400243** is **(64)(2)(67)** in base 256 and gcc's multi-character character constants use big-endian byte order, so `'@\2C'` yields the memory address of the desired string.

Finally, `puts` prints the (null-terminated) sting at that memory location and a trailing newline, creating 17 bytes of output.

[C (gcc)]: https://gcc.gnu.org/
[Try it online!]: https://tio.run/##S9ZNT07@/z9NQ7O6oLSkWEPdgclZXdO69n9mXolCbmJmnoYmVzUXJ1Demqv2PwA "C (gcc) – TIO Nexus"