Pick the brace style your project already uses
Match the repository even when you dislike its choice. A reformat spread across a file buries the real diff and makes git blame useless for that region, which costs more than the layout ever gains. For a project with no history yet, K&R at 4 spaces is the safest starting point.
| Style | Opening brace | Where you meet it |
|---|---|---|
| K&R | Same line as the statement | Linux kernel, BSD userland, most POSIX code |
| Allman | Own line, at the statement column | Windows SDK samples, MFC, 1990s embedded C |
| GNU | Own line, indented half a step | glibc, coreutils, GNU Coding Standards |
| Whitesmiths | Own line, at the body column | Instrument and industrial firmware |
The kernel case is worth knowing about. Its 8 column tabs look like an accident and are not. The kernel style document treats deep nesting as a design warning, so it makes each level expensive on purpose: run out of screen width and the function needs splitting. Set Indent to Tab with K&R braces to see what a patch has to look like before that project takes it.
What the Format button changes
Every line is rebuilt, not patched. Your source runs through a small C tokenizer first, so strings, character constants, comments and preprocessor lines are set aside before any spacing rule touches the code. That is what stops a brace inside a string literal from throwing off the indentation.
- Indentation comes from brace depth at the width you pick. Old tabs and mixed leading whitespace are replaced outright.
- Semicolons outside a
forheader break the line, so you get one statement per line. - Spacing follows normal C convention: around binary operators, none inside parentheses, none between a function name and its argument list, one space after
if,for,whileandswitch. - Prefix and postfix operators stay glued to their operand, so
*p,&x,-1andi++survive instead of turning into arithmetic. - Pointers normalize to
char *p. The star binds to the declarator, not the type, andchar* a, b;declares one pointer and one plain char. Right alignment keeps that visible. - Casts lose the gap before their value, and
caselabels indent underswitch. - Trailing whitespace goes, runs of blank lines collapse to one, and goto labels outdent a level.
Output replaces your input in the same box. CtrlZ brings the original back if you want to compare.
The macro that breaks your indentation
Directives take a separate path. They sit at column 0 so #ifdef ladders stay readable inside a nested function, whitespace between # and the directive name is removed, and backslash continuation lines get one level of indent under their directive. The body of a #define is left exactly as written, spacing included, because macro text is substituted verbatim and reformatting it risks changing what the compiler sees.
One pattern defeats all of that. A macro holding half a brace pair, the classic #define BEGIN {, breaks the depth counter for every line after it. The status bar reports the mismatch rather than guessing, and indentation past that point is unreliable. If you see a brace warning on code that compiles fine, a macro is almost always the reason.
Where this stops short
- Long lines are never wrapped. There is no column limit, so a 300 character condition stays 300 characters wide.
- Array and struct initializers keep the line breaks you wrote. A lookup table on one line stays on one line.
#includelines are neither sorted nor grouped.- Pointer detection is a heuristic built on type keywords and the
_tsuffix. A typedef namedMatrixinMatrix * m;reads as multiplication and gets spaced that way. - C++ files mostly survive, but classes, templates, namespaces and access labels are not handled. Use the C++ beautifier for those.
- Files past roughly 2 MB are refused rather than freezing the tab.
The output will not match clang-format line for line, and it is not meant to. This page is for reading code someone pasted at you. What lands in a commit should go through the config your repository already carries.
The same job in your editor
Three tools cover almost every C codebase and all of them run offline in a pre-commit hook.
clang-format -i --style=file src/*.c
indent -kr -i4 -nut reader.c
astyle --style=allman --indent=spaces=4 reader.cCommit the settings so the layout stops being a personal preference:
# .clang-format
BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Never
BreakBeforeBraces: Attach
PointerAlignment: Right
IndentCaseLabels: true
ColumnLimit: 100GNU indent ships with most distributions and predates clang by decades. It handles plain C fine through -kr, -gnu and -orig, though it has no idea what to do with newer attributes.
