Python Appears to Violate C Standard: Leading Underscores?

Hi Language Lawyers and Pythonistas,

Looking at an old draft C standard here, I see the following:

An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter.

So identifiers can denote macro names. Looking further, I see the following:

All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

And yet, the CPython implementation is using macro names beginning with _Py(in, for example, pyport.h):

#  define _Py_NO_RETURN

Does CPython have a good reason for doing this? I realize CPython is used by many many people and is sure to compile correctly with mainstream compilers like GCC and Clang, but does the project really gain anything by running against the C standard here?

1 Like

The “leading underscores” is a python agreement which means that this variable is private and you shouldn’t use it in your project or python won’t promise that it will always effective.

The quoted lines are from chapter 7 Library, in subsubsection 7.1.3 Identifiers and immediately follow the opening paragraph. Each begins with a ‘—’ that indicates subordination to this paragraph:

  1. Each header declares or defines all identifiers listed in its associated subclause, and
    optionally declares or defines identifiers listed in its associated future library directions
    subclause and identifiers which are always reserved either for any use or for use as file
    scope identifiers

The headers referred to are the standard C library .h files, from assert.h to wctype.h. It seems plausible to me that the reservation, whatever it means, only applies to library files.

In any case, Python was originally written in either K&R C or the first standard, C’89. The draft is dated 2007 so it must be what became C’11. I don’t believe CPython claims strict C11 conformity. It may not even yet allow use of all its features.

3 Likes

Yeah, this is not portable, based on the standard. However, any C implementation that breaks Python at this point is probably considered buggy itself. In retrospect, Python should have used something like Py_INTERNAL_ as the prefix. Continuing to use _Py now is fine, IMHO, but other prefixes should not be used and other C projects should not follow the example (using something like _<something> for “private” symbols).

3 Likes