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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox