[HN Gopher] Printf-Tac-Toe
       ___________________________________________________________________
        
       Printf-Tac-Toe
        
       Author : carlos-menezes
       Score  : 115 points
       Date   : 2026-03-08 12:01 UTC (4 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | danbruc wrote:
       | How did we end up with printf - within a loop - being Turing-
       | complete? Was it designed that way from the beginning? Were new
       | features added over time until we got there?
        
         | marmakoide wrote:
         | Having something Turing-complete is surprisingly easy, and it
         | hides everywhere. The repository have a small document that
         | explains how you can use printf() as a computer : it can
         | performs additions, logical union and negation, which is
         | enough.
         | 
         | It was unintentional, but Ken Thompson being Ken Thompson,
         | can't be 100% sure.
        
           | danbruc wrote:
           | So there was no extension of the functionality over time, all
           | the formats have been supported from day one?
        
             | st_goliath wrote:
             | The key features that is used here is the '%n' format
             | specifier, that fetches a pointer as the next argument, and
             | writes a character count back.
             | 
             | There is actually an interesting question here: was '%n'
             | always in printf, or was it added at one point?
             | 
             | I took a cursory look at some old Unix source archives at
             | TUHS: https://www.tuhs.org/cgi-bin/utree.pl
             | 
             | As far as I can tell from the PDP-11 assembly, Version 7
             | research Unix (relevant file: /usr/src/libc/stdio/doprnt.s)
             | does _not_ appear to implement it.
             | 
             | The 4.1BSD version of that file even _explicitly throws an
             | error_ , treating it as an invalid format specifier.
             | 
             | The implementation in a System III archive looks
             | suspiciously similar to the BSD one, also throwing an
             | error.
             | 
             | Only in a System V R4 archive (relevant file:
             | svr4/ucblib/libc/port/stdio/doprnt.c) I found an
             | implementation of "%n" that works as expected.
             | 
             | I guess it was added at some point to System V and through
             | that eventually made it into POSIX?
        
               | sltkr wrote:
               | I think it was first introduced in 4.3 BSD Tahoe
               | (released June 15, 1988): https://www.tuhs.org/cgi-
               | bin/utree.pl?file=4.3BSD-Tahoe/usr/...
               | 
               | This was an update to the earlier 4.3 BSD (1986) which
               | still implemented printf() in VAX assembly instead, and
               | doesn't support the %n feature.
               | 
               | So %n may have originally been implemented in 4.3 BSD
               | Tahoe and made its way into SVR4 subsequently.
        
           | gwern wrote:
           | List of examples: https://gwern.net/turing-complete
           | 
           | It was probably unintentional, yeah, I don't recall any
           | mentions of early printf being overloaded to do stuff, nor is
           | it clear why you would do that since you're using it in a
           | much more convenient Turing-complete language already (C).
        
       | idorozin wrote:
       | This is both impressive and slightly terrifying. Format strings
       | are way more powerful than most people realize.
        
       | JKCalhoun wrote:
       | Contestant: "I'll take _My Dirty Programming Secrets_ for 100,
       | Alex. "
       | 
       | Alex: "Its primary purpose is to serve as The One True Debugger."
       | 
       | (It has certainly served me well.)
        
       | LoganDark wrote:
       | To be fair, this is actually `scanf` and `printf` in a loop. The
       | `scanf` is buried in the `arg` define.
        
       | binaryturtle wrote:
       | That's the content why I check HN! :)
        
       | ivanjermakov wrote:
       | No surprise Log4J attack was that big. Amount of logic one can
       | fit into text formatting is immense.
        
       | mrngm wrote:
       | [2020], and written for IOCCC: The International Obfuscated C
       | Code Contest.
       | 
       | This was awarded "Best of Show - abuse of libc" at the time[0].
       | See also the judges' remarks[1]:
       | 
       |  _This program consists of a single printf(3) statement wrapped
       | in a while loop. You would not think that this would amount to
       | much, but you would be very, very wrong. A clue to what is
       | happening and how this works is encoded in the ASCII art of the
       | program source._
       | 
       | [0] https://www.ioccc.org/2020/index.html
       | 
       | [1] https://www.ioccc.org/2020/carlini/index.html
        
       ___________________________________________________________________
       (page generated 2026-03-12 23:01 UTC)