Where implementations differ
The original definition of brainfuck is a table and three sentences. It does not say how large a number a cell can hold, what happens at the ends of the tape, or what the read command does when the input has run out. Implementations fill these gaps in different ways, and already did so in 1993: the compiler and the interpreter in the original package do not agree with each other [1].
Why there are differences
Nobody ever wrote a standard. The author says so: there is no formal standard, and people disagree about how large a cell is and about what happens at the end of the input [2]. What exists are three careful descriptions by other people, which mostly agree: Brian Raiter's "Portable Brainfuck" [3], Daniel Cristofani's reference and his letter to implementors [4] [5], and the conventions on the Esolang wiki [6].
The differences are as old as the language. The 1993 package holds a compiler and an interpreter, and reading their sources shows that they differ [1]:
- The compiler gives a program 30,000 cells. The interpreter declares 5,000 and stops with "RANGE ERROR" as soon as the pointer goes past cell 100.
- The compiler of this second version works on bytes. The README says that the first version worked on "longwords", which on the Amiga are numbers of 32 bits.
- At the end of the input the interpreter stores whatever C's
getchar()returns. As we read the compiler's source, a compiled program asks the system for one byte and, when none comes, leaves the cell as it was.
So "what the original did" is not one answer.
Cell size and wrapping
The program below is one command, run on cell 0. Choose the cell size and the command, and slide the number cell 0 starts at: to 255 for +, or to 0 for -. Press Play:
With 8 bits and a start of 255, the one + left 0: the cell went round. Below 0 comes the largest number the cell can hold, and one more than the largest number is 0. This is called wrapping. With cells of 8 bits the largest number is 255, so 255 + 1 = 0 and 0 − 1 = 255; choose 16 bits and the same commands give 256 and 65,535. The values of a cell are a ring.
What the descriptions say:
- Cells of 8 bits that wrap are by far the most common, and the Esolang wiki gives them as the normal case [6]. Cristofani: a cell holds a whole number, "minimally and usually one byte" [4].
- Raiter's minimum is smaller: a cell must at least hold 0 to 127, and wrapping "is not required" [3].
- Implementations with 16-bit and 32-bit cells exist, and some let you choose [7]. A few have cells without any limit.
Why it matters:
- Short programs lean on wrapping. The shortest known ways to make many numbers go below zero on purpose: 255 is one
-with wrapping and 33 commands without [8]. - Speed. The loop [-] empties a cell by counting down. On 8-bit cells that is at most 255 rounds. On 32-bit cells it can be four billion, unless the implementation recognises the loop (see clear loops).
- Large programs may need large cells. The chat models of this site need wrapping cells of 32 bits and print nonsense on 8-bit cells. A tool chain that compiles C to brainfuck, ELVM, needs the opposite: its README says "you need implementations with 8bit cells" [9].
A program can find out the size of its cells by counting how often it can double a number before it becomes 0. A well-known test program, bitwidth.b, does this and reports what it found [7].
The length of the tape and its ends
The original gives 30,000 cells [1], and that number became the custom: Cristofani and the Esolang wiki both ask for at least 30,000 [4] [6]. Raiter's minimum is 9,999, so that very small interpreters can keep the pointer in four digits [3]. Many implementations give more, or let the tape grow.
The pointer starts on the leftmost cell. The tape below has six cells (I'm showing six; the original has 30,000). Slide the number of moves to the right, then the number of moves to the left, and press Play:
Five moves to the right bring the pointer to the last cell. A sixth, or one move left of the first cell, takes it off the tape, and this machine stops with a message. Moving left from the leftmost cell is an error in the program. What happens then is "unpredictable" in Cristofani's word [4] and undefined in Raiter's [3]. In practice an implementation does one of these:
- stops with an error (the machine on these pages does this);
- goes round to the other end of the tape;
- has cells on the left as well;
- writes outside its memory and crashes, or worse.
Some very short programs use cells to the left of the start on purpose. The shortest known "Hello, World!" needs five of them [6]. Such a program is short, not portable.
The end of the input
The program below copies its input to its output: read, and while the cell is not 0, print and read again. The input is "hello", and you can change it. Choose what the read command does at the end of the input, and press Play:
The loop ends when a read gives 0. That works only where the read command stores 0 at the end of the input. Where it stores −1 the cell becomes 255 and the program prints that for ever. Where the cell is left as it was, the program prints the last letter for ever. The figure follows a run for at most 5,000 steps and says so when the program is still going, because that run would never reach its end.
These are the three behaviours you will meet: store 0, store −1, or leave the cell unchanged [5] [3] [6]. Raiter calls it "frequently the most problematic issue" for a programmer who wants a program to run everywhere [3]. Cristofani prefers "unchanged", because a program can then choose its own value by setting the cell just before it reads; he asks implementations to offer all three [5].
The next program does the same job but is written to stop under all three. Run it under each of them in turn:
Now the status line always says it finished. Before every read the program empties the cell with [-]. After the read the cell is 0 in two of the three cases. Then it adds one: in the third case, −1 becomes 0. It goes on only if the cell was neither. The price: the program also stops at a character with code 0 or 255. Ordinary text has neither.
New lines
Operating systems mark the end of a line in different ways: one character with code 10, or a 13 followed by a 10. Brainfuck programs almost always use 10 alone, as Müller's own example programs do [5] [1]. Cristofani asks implementations to make this work on every system: a program should receive a 10 for each end of line in its input, and a 10 it prints should end a line, with an option to switch that translation off for input that is not text [5].
For a program this means: print 10 for a new line and expect 10 at the end of a line you read. If you run it somewhere that sends 13 as well, treat 13 as a character to skip.
Smaller differences
- Brackets that do not match
- The original compiler does not check; the original interpreter reports them [1]. Most implementations today refuse to run such a program.
- The debug command
# - The original interpreter prints the first ten cells when it meets a
#, if it was started with an extra argument [1]. Some implementations kept this. Everywhere else#is a comment. Müller's own "Hello World!" has one in it. - The separator
! - An interpreter that reads the program and its input from the same stream needs to know where one ends. The custom is an exclamation mark [5]. In a program file it is a comment.
- When output appears
- A program that asks a question and waits for an answer needs its output shown at once, not saved up until the end. Cristofani asks for this [5]; not every implementation does it.
- Characters above 127
- The original worked with single bytes. What a byte above 127 looks like on screen depends on the system; today it is usually read as part of a UTF-8 character [6]. A program that prints only codes 10 and 32 to 126 is safe.
Compatibility table
The table below puts the answers side by side. The first two columns are the two programs of the 1993 package, read from their sources. The next three are the written descriptions. The last is the machine in the figures of this reference.
| Open point | 1993 compiler | 1993 interpreter | Raiter, "Portable Brainfuck" | Cristofani | Esolang wiki | The figures here |
|---|---|---|---|---|---|---|
| Cell size | one byte (the first version: 32 bits) | one C char | at least 0 to 127 | at least one byte, usually one byte | normally 8 bits | 8 bits; 16 or 32 where offered |
| Past the largest value | wraps (a byte addition) | whatever a char does | usually wraps; not required | may or may not wrap | should wrap | wraps |
| Cells | 30,000 (README) | 5,000 declared; error past cell 100 | at least 9,999 | at least 30,000 | at least 30,000 | a short tape, as many cells as are drawn |
| Pointer off the tape | not checked | "RANGE ERROR", stops | undefined | unpredictable | no cells left of the start | stops with a message |
| Read at end of input | cell unchanged (our reading of the source) | stores the value of getchar(), in C normally −1 | one of: 0, −1, unchanged | prefers unchanged; offer all three | offer all three | 0; or −1 or unchanged where offered |
| New line | not said; the examples print 10 | not said | not said | 10, translated for the system | 10 | 10 |
| Unmatched brackets | not checked | "UNBALANCED BRACKETS" | undefined | not said | not said | refuses to run |
| Other characters | ignored | ignored; # prints cells | ignored | ignored; # and ! allowed | ignored | ignored |
The chat programs of this site are outside this table on purpose: they need 32-bit wrapping cells and a tape of 188 million cells or more. See Notable programs.
Programs that work everywhere
Seven rules. A program that keeps them runs the same on almost every implementation.
- Keep every cell between 0 and 127 if you can; never above 255. Then the size of a cell does not matter.
- Do not count on wrapping. Never take one off a cell that holds 0, and never empty a cell with [+]. If you do use wrapping, say so in a comment.
- Never move left of the cell you started on.
- Use fewer than 9,999 cells, or at least fewer than 30,000.
- Empty a cell before you read into it, and treat both 0 and "all ones" as the end of the input, as the second program under the end of the input does.
- Print 10 for a new line, and print only codes 10 and 32 to 126.
- Match your brackets, and keep punctuation out of comments.
To see what an implementation does, run Cristofani's small test programs on it. They report how new lines and the end of the input are handled and how far the tape reaches [10].
And when a program does need something special, as many good ones do, say what it needs at the top: the cell size, the tape length, the behaviour at the end of the input.
Limits
- The two "1993" columns are our own reading of the source files
bfc.asmandbfi.c. We did not run them on an Amiga. - "Most common" is the judgement of the descriptions we cite. We know of no count of implementations.
Read next
Notes and sources
Where a source is a community wiki or the author's own account, the entry or the text says so.
- Urban Müller, brainfuck-2.lha, Aminet, dev/lang, dated 9 June 1993: the package page on Aminet. We read the files in the archive:
README,bfc.asm(the compiler),bfi.c(the interpreter) and the six example programs. Sizes and dates are those of the archive listing. Opened 11 October 2026. - Urban Müller, talk at Tamedia TX, 2017, read as the community transcript on the Esolang wiki: Tamedia TX 2017 transcript. The transcript says its last page is missing. Wikipedia gives the title as "Brainfuck, or how I learned to change the problem" and the date as 13 June 2017; we did not watch the recording. Opened 11 October 2026.
- Brian Raiter, "Portable Brainfuck": the portability page on muppetlabs.com. Opened 11 October 2026.
- Daniel B Cristofani, "Yet another brainfuck reference": the reference on brainfuck.org. Opened 11 October 2026.
- Daniel B Cristofani, "The Epistle to the Implementors": the epistle on brainfuck.org. Opened 11 October 2026.
- Esolang wiki, "Brainfuck": the wiki article on brainfuck. A community wiki; we use it for conventions and for its list of results, and name it where it is our only source. Opened 11 October 2026.
- rdebath, Brainfuck repository: rdebath/Brainfuck on GitHub. Holds the Tritium interpreter, translators to many languages, test programs and a copy of Müller's 1993 compiler. Opened 11 October 2026.
- Esolang wiki, "Brainfuck constants": the wiki's table of constants. Opened 11 October 2026.
- shinh, ELVM Compiler Infrastructure, README: shinh/elvm on GitHub. Opened 11 October 2026.
- Daniel B Cristofani, tests.b: test programs for implementations on brainfuck.org. Opened 11 October 2026.