From: Alejandro Colomar <alx@kernel.org>
To: Seth McDonald <sethmcmail@pm.me>
Cc: linux-man@vger.kernel.org
Subject: History of const in C++, C89, and POSIX.1-1988 (was: [PATCH v1 02/19] man/man2/access.2: HISTORY: Specify different)
Date: Tue, 20 Jan 2026 14:52:22 +0100 [thread overview]
Message-ID: <aW96GgzoYUurH5FS@devuan> (raw)
In-Reply-To: <aW9xYhsFpNxlo3C5@McDaDebianPC>
[-- Attachment #1: Type: text/plain, Size: 6796 bytes --]
Hi Seth,
On Tue, Jan 20, 2026 at 12:13:32PM +0000, Seth McDonald wrote:
> On Tue, Jan 20, 2026 at 02:34:08AM +0100, Alejandro Colomar wrote:
> > Hi Seth,
> >
> > On Mon, Jan 19, 2026 at 11:55:06AM +0000, Seth McDonald wrote:
> > > access(2) was specified in POSIX.1-1988 with the prototype
> > > int access(char *path, int amode); [1]
> > >
> > > POSIX.1-1990 then changed the prototype to
> > > int access(const char *path, int amode); [2]
> >
> > I suspect this is common to all APIs specified in those standards,
> > right? Or is it specific to this API?
> >
> > 'const' was invented by ANSI C89, so I expect the change was around that
> > time.
>
> I believe the qualifier is indeed absent from any* specified prototype
> in POSIX.1-1988. Which would make sense if it was first specified in
> C89. Similar to how void pointers didn't first appear in POSIX.1-1988,
> but after being added in C89, appeared in POSIX.1-1990.
>
> *Interestingly enough, the appendix of POSIX.1-1988 (section B.2.2.4,
> page 192) does acknowledge the const qualifier when describing the C
> Standard's atoi(3) function. Which makes me think that POSIX was
> actually aware of C89's upcoming additions to the language. Which in
> turn begs the question: why, if they knew about it, was it not used in
> the POSIX.1-1988 standard? Multiple other types and functions were
> included in POSIX.1-1988 because they were (going to be) in C89.
I don't know the year in which const was added to the C89 drafts, but
I suspect it was near the release.
The C89 rationale says:
The syntax and semantics of const were adapted from C++;
the concept itself has appeared in other languages.
Also, qualifier rules were made more strict near the release of C89, as
they discovered the dangers of assigning a 'char**' to a 'const char**'
near the release. C++ had more time to investigate the issue before
C++98, and so the came up with the better rules they have.
C2y will likely adopt the C++ rules for qualifiers, as proposed (by me)
in n3749 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3749.txt>.
We will vote this in a month or two.
And after we vote n3749, we want to improve the rules even further, as
proposed by Chris Bazley in n3674
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3674.pdf>.
> This is just me thinking out loud here. I don't mind if the answer
> isn't known. Although if the answer is relevant/broad enough, it may be
> useful to mention it in standards(7).
We might need a qualifiers(7) manual page. Especially, once their rules
are modified in ISO C2y. Alternatively, we may need a new section
man3qual, with an intro(3qual) page talking about this, and then
const(3qual) and volatile(3qual) to document the usual qualifiers, plus
a restrict(3qual) documenting how irremediably broken that monster is,
and _Atomic(3qual) also documenting that qualifier (which I never really
understood well, and from what the committee is talking now, they don't
seem to like it either).
> Something like "POSIX.1-1988
> attempted to align its specification with the features/syntax of the
> (not yet released) C89 standard, but for ABC reasons, could not use XYZ
> language features."
>
> > On the change itself, it wasn't a breaking change: programs written
> > before the addition of const wouldn't notice that const has been added
> > to the prototype.
> >
> > The change would be noticed by a program written today, but compiled in
> > such an old system. However, I expect such a program to be aware that
> > pre-ANSI C was different, and it would have to adapt to it anyway.
> > const would be something that would have to be globally ignored, with
> > something like
> >
> > #define const
> >
> > Given this should be of no importance to users, I'd prefer not
> > documenting this difference.
> >
> > What do you think?
>
> It's important to note that since the type 'const char*' is a pointer to
> a const char, rather than a const pointer to a char, the type is
> incompatible with its non-const counterpart. That is, 'const char*' and
> 'char*' are technically incompatible datatypes.
>
> This can be seen by attempting to compile the following C program:
>
> #include <stdio.h>
>
> int say_hi(const char* str)
> {
> return printf("Hi %s", str);
> }
>
> int main(void)
> {
> int (*func)(char*) = say_hi;
> func("Linux");
> return 0;
> }
>
> On GCC at least, you should get an incompatible-pointer-types error.
>
> Now imagine an old program that was built to be compatible with
> specifically POSIX.1-1988, and which liked to use function pointers a
> little too much. If it happened to use function pointers to functions
> whose parameters weren't const-qualified in POSIX.1-1988, but were in
> later versions, then it (to my understanding) cannot be linked to an
> implementation of a later POSIX version without either errors or the
> possibility of undefined behaviour.
>
> While I cannot guarantee that such a program exists, what I can say is
> that I have used pointers to library functions in my own code before.
> So I don't think it'd be unusual for such a program to exist.
>
> Given this, I do think this still may be notable enough to document.
> Perhaps not in every such function - as that can get quite repetitive -
> but instead as a property of the POSIX.1-1988 standard as a whole. But
> feel free to let me know if there's something I missed here.
I suspect back then this was not a big problem.
Function prototypes were also invented by C89 (although it seems to have
been invented in an earlier draft than const, by the fact that
POSIX.1-1988 has prototypes but not const).
Before function prototypes, functions were declared as
int f();
and function pointers were declared as
int (*fp)();
For example, here's how qsort(3) was implemented in 4.3BSD (1986):
alx@devuan:~/src/unix/unix/4.3BSD$ cat ./usr/src/lib/libc/gen/qsort.c \
| sed -n \
-e '/^qsort/,/^{/p' \
-e '/compar\>/p' \
-e '/qcmp/p' \
-e '/^}/{p;q}' \
| uniq;
static int (*qcmp)(); /* the comparison routine */
qsort(base, n, size, compar)
char *base;
int n;
int size;
int (*compar)();
{
qcmp = compar;
if (qcmp(j, lo) > 0)
while (qcmp(hi -= qsz, min) > 0)
}
Even though in 1988 function prototypes already existed, I expect code
didn't start using them quickly, and thus no real incompatibilities
existed.
About when function prototypes were introduced... POSIX.1-1988 already
uses them, and SVID Issue 2 (~1986) doesn't, so it was somewhere between
those years.
Have a lovely day!
Alex
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2026-01-20 13:52 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-19 11:54 [PATCH v1 00/19] man/man2/*: Update history of syscalls A-CH Seth McDonald
2026-01-19 11:54 ` [PATCH v1 01/19] man/man2/access.2: HISTORY: Update first POSIX appearance of access(2) Seth McDonald
2026-01-19 11:55 ` [PATCH v1 02/19] man/man2/access.2: HISTORY: Specify different access(2) prototypes Seth McDonald
2026-01-20 1:34 ` Alejandro Colomar
2026-01-20 12:13 ` Seth McDonald
2026-01-20 13:52 ` Alejandro Colomar [this message]
2026-01-20 13:59 ` History of const in C++, C89, and POSIX.1-1988 (was: [PATCH v1 02/19] man/man2/access.2: HISTORY: Specify different) Alejandro Colomar
2026-01-21 6:12 ` Seth McDonald
2026-01-21 14:41 ` On restrict (a broken qualifier) Alejandro Colomar
2026-01-21 14:44 ` History of const in C++, C89, and POSIX.1-1988 (was: [PATCH v1 02/19] man/man2/access.2: HISTORY: Specify different) Alejandro Colomar
2026-01-19 11:55 ` [PATCH v1 03/19] man/man2/access.2: HISTORY: Update first POSIX appearance of faccessat(2) Seth McDonald
2026-01-19 11:55 ` [PATCH v1 04/19] man/man2/alarm.2: HISTORY: Update first POSIX appearance of alarm(2) Seth McDonald
2026-01-19 11:55 ` [PATCH v1 05/19] man/man2/chdir.2: HISTORY: Split chdir(2) and fchdir(2) Seth McDonald
2026-01-19 11:55 ` [PATCH v1 06/19] man/man2/chdir.2: HISTORY: Update first POSIX appearance of chdir(2) Seth McDonald
2026-01-19 11:56 ` [PATCH v1 07/19] man/man2/chdir.2: HISTORY: Specify different chdir(2) prototypes Seth McDonald
2026-01-19 11:56 ` [PATCH v1 08/19] man/man2/chdir.2: HISTORY: Update first POSIX appearance of fchdir(2) Seth McDonald
2026-01-19 11:56 ` [PATCH v1 09/19] man/man2/chmod.2: HISTORY: Split chmod(2) and fchmod(2) Seth McDonald
2026-01-19 11:56 ` [PATCH v1 10/19] man/man2/chmod.2: HISTORY: Update first POSIX appearance of chmod(2) Seth McDonald
2026-01-19 11:57 ` [PATCH v1 11/19] man/man2/chmod.2: HISTORY: Specify different chmod(2) prototypes Seth McDonald
2026-01-19 11:57 ` [PATCH v1 12/19] man/man2/chmod.2: HISTORY: Update first POSIX appearance of fchmod(2) Seth McDonald
2026-01-19 11:57 ` [PATCH v1 13/19] man/man2/chmod.2: HISTORY: Update first POSIX appearance of AT_SYMLINK_NOFOLLOW Seth McDonald
2026-01-19 11:57 ` [PATCH v1 14/19] man/man2/chown.2: HISTORY: Split chown(2), fchown(2), and lchown(2) Seth McDonald
2026-01-19 11:57 ` [PATCH v1 15/19] man/man2/chown.2: HISTORY: Update first POSIX appearance of chown(2) Seth McDonald
2026-01-19 11:58 ` [PATCH v1 16/19] man/man2/chown.2: HISTORY: Specify different chown(2) prototypes Seth McDonald
2026-01-19 11:58 ` [PATCH v1 17/19] man/man2/chown.2: HISTORY: Update first SUS appearance of fchown(2) Seth McDonald
2026-01-19 11:58 ` [PATCH v1 18/19] man/man2/chown.2: HISTORY: Update first POSIX appearance of lchown(2) Seth McDonald
2026-01-19 11:58 ` [PATCH v1 19/19] man/man2/chroot.2: HISTORY: Update first SUS appearance of chroot(2) Seth McDonald
2026-01-20 1:50 ` [PATCH v1 00/19] man/man2/*: Update history of syscalls A-CH Alejandro Colomar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aW96GgzoYUurH5FS@devuan \
--to=alx@kernel.org \
--cc=linux-man@vger.kernel.org \
--cc=sethmcmail@pm.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.