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 . 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 . > 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 > > 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 --