CINXE.COM
PEP 7 – Style Guide for C Code | peps.python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 7 – Style Guide for C Code | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0007/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 7 – Style Guide for C Code | peps.python.org'> <meta property="og:description" content="This document gives coding conventions for the C code comprising the C implementation of Python. Please see the companion informational PEP describing style guidelines for Python code."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0007/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="This document gives coding conventions for the C code comprising the C implementation of Python. Please see the companion informational PEP describing style guidelines for Python code."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 7</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 7 – Style Guide for C Code</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">05-Jul-2001</dd> <dt class="field-odd">Post-History<span class="colon">:</span></dt> <dd class="field-odd"><p></p></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#introduction">Introduction</a></li> <li><a class="reference internal" href="#c-dialect">C dialect</a></li> <li><a class="reference internal" href="#code-lay-out">Code lay-out</a></li> <li><a class="reference internal" href="#naming-conventions">Naming conventions</a></li> <li><a class="reference internal" href="#documentation-strings">Documentation Strings</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="introduction"> <h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2> <p>This document gives coding conventions for the C code comprising the C implementation of Python. Please see the companion informational PEP describing <a class="pep reference internal" href="../pep-0008/" title="PEP 8 – Style Guide for Python Code">style guidelines for Python code</a>.</p> <p>Note, rules are there to be broken. Two good reasons to break a particular rule:</p> <ol class="arabic simple"> <li>When applying the rule would make the code less readable, even for someone who is used to reading code that follows the rules.</li> <li>To be consistent with surrounding code that also breaks it (maybe for historic reasons) – although this is also an opportunity to clean up someone else’s mess (in true XP style).</li> </ol> </section> <section id="c-dialect"> <h2><a class="toc-backref" href="#c-dialect" role="doc-backlink">C dialect</a></h2> <ul class="simple"> <li>Python 3.11 and newer versions use C11 without <a class="reference external" href="https://en.wikipedia.org/wiki/C11_%28C_standard_revision%29#Optional_features">optional features</a>. The public C API should be compatible with C++.</li> <li>Python 3.6 to 3.10 use C89 with several select C99 features:<ul> <li>Standard integer types in <code class="docutils literal notranslate"><span class="pre"><stdint.h></span></code> and <code class="docutils literal notranslate"><span class="pre"><inttypes.h></span></code>. We require the fixed width integer types.</li> <li><code class="docutils literal notranslate"><span class="pre">static</span> <span class="pre">inline</span></code> functions</li> <li>designated initializers (especially nice for type declarations)</li> <li>intermingled declarations</li> <li>booleans</li> <li>C++-style line comments</li> </ul> </li> <li>Python versions before 3.6 used ANSI/ISO standard C (the 1989 version of the standard). This meant (amongst many other things) that all declarations must be at the top of a block (not necessarily at the top of function).</li> <li>Don’t use compiler-specific extensions, such as those of GCC or MSVC (e.g. don’t write multi-line strings without trailing backslashes).</li> <li>All function declarations and definitions must use full prototypes (i.e. specify the types of all arguments).</li> <li>No compiler warnings with major compilers (gcc, VC++, a few others).</li> <li><code class="docutils literal notranslate"><span class="pre">static</span> <span class="pre">inline</span></code> functions should be preferred over macros in new code.</li> </ul> </section> <section id="code-lay-out"> <h2><a class="toc-backref" href="#code-lay-out" role="doc-backlink">Code lay-out</a></h2> <ul> <li>Use 4-space indents and no tabs at all.</li> <li>No line should be longer than 79 characters. If this and the previous rule together don’t give you enough room to code, your code is too complicated – consider using subroutines.</li> <li>No line should end in whitespace. If you think you need significant trailing whitespace, think again – somebody’s editor might delete it as a matter of routine.</li> <li>Function definition style: function name in column 1, outermost curly braces in column 1, blank line after local variable declarations.<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">int</span> <span class="nf">extra_ivars</span><span class="p">(</span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">type</span><span class="p">,</span><span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">base</span><span class="p">)</span> <span class="p">{</span> <span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">t_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_BASICSIZE</span><span class="p">(</span><span class="n">type</span><span class="p">);</span> <span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_BASICSIZE</span><span class="p">(</span><span class="n">base</span><span class="p">);</span> <span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">t_size</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="n">b_size</span><span class="p">);</span><span class="w"> </span><span class="cm">/* type smaller than base! */</span> <span class="w"> </span><span class="p">...</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span> <span class="p">}</span> </pre></div> </div> </li> <li>Code structure: one space between keywords like <code class="docutils literal notranslate"><span class="pre">if</span></code>, <code class="docutils literal notranslate"><span class="pre">for</span></code> and the following left paren; no spaces inside the paren; braces are required everywhere, even where C permits them to be omitted, but do not add them to code you are not otherwise modifying. All new C code requires braces. Braces should be formatted as shown:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">mro</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="p">...</span> <span class="p">}</span> <span class="k">else</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="p">...</span> <span class="p">}</span> </pre></div> </div> </li> <li>The return statement should <em>not</em> get redundant parentheses:<div class="bad highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">return</span><span class="p">(</span><span class="n">albatross</span><span class="p">);</span><span class="w"> </span><span class="cm">/* incorrect */</span> </pre></div> </div> <p>Instead:</p> <div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">return</span><span class="w"> </span><span class="n">albatross</span><span class="p">;</span><span class="w"> </span><span class="cm">/* correct */</span> </pre></div> </div> </li> <li>Function and macro call style: <code class="docutils literal notranslate"><span class="pre">foo(a,</span> <span class="pre">b,</span> <span class="pre">c)</span></code> – no space before the open paren, no spaces inside the parens, no spaces before commas, one space after each comma.</li> <li>Always put spaces around assignment, Boolean and comparison operators. In expressions using a lot of operators, add spaces around the outermost (lowest-priority) operators.</li> <li>Breaking long lines: if you can, break after commas in the outermost argument list. Always indent continuation lines appropriately, e.g.:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PyExc_TypeError</span><span class="p">,</span> <span class="w"> </span><span class="s">"cannot create '%.100s' instances"</span><span class="p">,</span> <span class="w"> </span><span class="n">type</span><span class="o">-></span><span class="n">tp_name</span><span class="p">);</span> </pre></div> </div> </li> <li>When you break a long expression at a binary operator, braces should be formatted as shown:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">type</span><span class="o">-></span><span class="n">tp_dictoffset</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span> <span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">base</span><span class="o">-></span><span class="n">tp_dictoffset</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span> <span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">type</span><span class="o">-></span><span class="n">tp_dictoffset</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">b_size</span> <span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">t_size</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">b_size</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="p">))</span> <span class="p">{</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="cm">/* "Forgive" adding a __dict__ only */</span> <span class="p">}</span> </pre></div> </div> <p>It’s OK to put operators at ends of lines, especially to be consistent with surrounding code. (See <a class="reference internal" href="../pep-0008/#pep8-operator-linebreak"><span class="std std-ref">PEP 8</span></a> for a longer discussion.)</p> </li> <li>Vertically align line continuation characters in multi-line macros.</li> <li>Macros intended to be used as a statement should use the <code class="docutils literal notranslate"><span class="pre">do</span> <span class="pre">{</span> <span class="pre">...</span> <span class="pre">}</span> <span class="pre">while</span> <span class="pre">(0)</span></code> macro idiom, without a final semicolon. Example:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#define ADD_INT_MACRO(MOD, INT) \</span> <span class="cp"> do { \</span> <span class="cp"> if (PyModule_AddIntConstant((MOD), (#INT), (INT)) < 0) { \</span> <span class="cp"> goto error; \</span> <span class="cp"> } \</span> <span class="cp"> } while (0)</span> <span class="c1">// To be used like a statement with a semicolon:</span> <span class="n">ADD_INT_MACRO</span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">SOME_CONSTANT</span><span class="p">);</span> </pre></div> </div> </li> <li><code class="docutils literal notranslate"><span class="pre">#undef</span></code> file local macros after use.</li> <li>Put blank lines around functions, structure definitions, and major sections inside functions.</li> <li>Comments go before the code they describe.</li> <li>All functions and global variables should be declared static unless they are to be part of a published interface.</li> <li>For external functions and variables, we always have a declaration in an appropriate header file in the “Include” directory, which uses the <code class="docutils literal notranslate"><span class="pre">PyAPI_FUNC()</span></code> macro and <code class="docutils literal notranslate"><span class="pre">PyAPI_DATA()</span></code> macro, like this:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyAPI_FUNC</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="n">PyObject_Repr</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="p">);</span> <span class="n">PyAPI_DATA</span><span class="p">(</span><span class="n">PyTypeObject</span><span class="p">)</span><span class="w"> </span><span class="n">PySuper_Type</span><span class="p">;</span> </pre></div> </div> </li> </ul> </section> <section id="naming-conventions"> <h2><a class="toc-backref" href="#naming-conventions" role="doc-backlink">Naming conventions</a></h2> <ul class="simple"> <li>Use a <code class="docutils literal notranslate"><span class="pre">Py</span></code> prefix for public functions; never for static functions. The <code class="docutils literal notranslate"><span class="pre">Py_</span></code> prefix is reserved for global service routines like <code class="docutils literal notranslate"><span class="pre">Py_FatalError</span></code>; specific groups of routines (e.g. specific object type APIs) use a longer prefix, e.g. <code class="docutils literal notranslate"><span class="pre">PyString_</span></code> for string functions.</li> <li>Public functions and variables use MixedCase with underscores, like this: <code class="docutils literal notranslate"><span class="pre">PyObject_GetAttr</span></code>, <code class="docutils literal notranslate"><span class="pre">Py_BuildValue</span></code>, <code class="docutils literal notranslate"><span class="pre">PyExc_TypeError</span></code>.</li> <li>Occasionally an “internal” function has to be visible to the loader; we use the <code class="docutils literal notranslate"><span class="pre">_Py</span></code> prefix for this, e.g.: <code class="docutils literal notranslate"><span class="pre">_PyObject_Dump</span></code>.</li> <li>Macros should have a MixedCase prefix and then use upper case, for example: <code class="docutils literal notranslate"><span class="pre">PyString_AS_STRING</span></code>, <code class="docutils literal notranslate"><span class="pre">Py_PRINT_RAW</span></code>.</li> <li>Macro parameters should use <code class="docutils literal notranslate"><span class="pre">ALL_CAPS</span></code> style, so they are easily distinguishable from C variables and struct members.</li> </ul> </section> <section id="documentation-strings"> <h2><a class="toc-backref" href="#documentation-strings" role="doc-backlink">Documentation Strings</a></h2> <ul> <li>Use the <code class="docutils literal notranslate"><span class="pre">PyDoc_STR()</span></code> or <code class="docutils literal notranslate"><span class="pre">PyDoc_STRVAR()</span></code> macro for docstrings to support building Python without docstrings (<code class="docutils literal notranslate"><span class="pre">./configure</span> <span class="pre">--without-doc-strings</span></code>).</li> <li>The first line of each function docstring should be a “signature line” that gives a brief synopsis of the arguments and return value. For example:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">myfunction__doc__</span><span class="p">,</span> <span class="s">"myfunction(name, value) -> bool</span><span class="se">\n\n</span><span class="s">\</span> <span class="s">Determine whether name and value make a valid pair."</span><span class="p">);</span> </pre></div> </div> <p>Always include a blank line between the signature line and the text of the description.</p> <p>If the return value for the function is always <code class="docutils literal notranslate"><span class="pre">None</span></code> (because there is no meaningful return value), do not include the indication of the return type.</p> </li> <li>When writing multi-line docstrings, be sure to always use backslash continuations, as in the example above, or string literal concatenation:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">myfunction__doc__</span><span class="p">,</span> <span class="s">"myfunction(name, value) -> bool</span><span class="se">\n\n</span><span class="s">"</span> <span class="s">"Determine whether name and value make a valid pair."</span><span class="p">);</span> </pre></div> </div> <p>Though some C compilers accept string literals without either:</p> <div class="bad highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/* BAD -- don't do this! */</span> <span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">myfunction__doc__</span><span class="p">,</span> <span class="s">"myfunction(name, value) -> bool</span><span class="se">\n\n</span> <span class="n">Determine</span><span class="w"> </span><span class="n">whether</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">valid</span><span class="w"> </span><span class="n">pair</span><span class="p">.</span><span class="s">");</span> </pre></div> </div> <p>not all do; the MSVC compiler is known to complain about this.</p> </li> </ul> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0007.rst">https://github.com/python/peps/blob/main/peps/pep-0007.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0007.rst">2024-09-09 14:02:27 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#introduction">Introduction</a></li> <li><a class="reference internal" href="#c-dialect">C dialect</a></li> <li><a class="reference internal" href="#code-lay-out">Code lay-out</a></li> <li><a class="reference internal" href="#naming-conventions">Naming conventions</a></li> <li><a class="reference internal" href="#documentation-strings">Documentation Strings</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0007.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>