The argv
and envp
arguments to execve()
are not pointers to const
in order to preserve backwards compatibility with valid C code that was written before const
was added to C.
C first appeared in 1972. Later on, const
was added to C in 1987.
In order to maintain compatibility with pre-const
code, the updated-with-const
declaration of execve()
must be able to accept non-const
inputs. C does not allow assignments from char *[]
to const char *[]
. This can be verified by trying (and failing) to compile the following program:
void foo ( const char * argv[] ) { return; }
void main ( int argc, char * argv[] ) { foo ( argv ); }
Therefore, char *const[]
is the strictest type that is backwards compatible with pre-const
code.
The question provides a link to the POSIX documentation for execve()
. The linked POSIX documentation does explain this as follows:
The statement about argv[]
and envp[]
being constants is included to
make explicit to future writers of language bindings that these
objects are completely constant. Due to a limitation of the ISO C
standard, it is not possible to state that idea in standard C. ...
Actually, to be precise: it is not possible to state that idea in a way that is backwards compatible with pre-const
code.
... Specifying two levels of const
- qualification for the argv[]
and
envp[]
parameters for the exec functions may seem to be the natural
choice, given that these functions do not modify either the array of
pointers or the characters to which the function points, but this
would disallow existing correct code. Instead, only the array of
pointers is noted as constant. The table of assignment compatibility
for dst= src derived from the ISO C standard summarizes the
compatibility:
dst: char *[] const char *[] char *const[] const char *const[]
src:
char *[] VALID - VALID -
const char *[] - VALID - VALID
char * const [] - - VALID -
const char *const[] - - - VALID
Since all existing code ...
Meaning all code that existed prior to const
being added to C.
... has a source type matching the first row, the
column that gives the most valid combinations is the third column. The
only other possibility is the fourth column, but using it would
require a cast on the argv
or envp
arguments. It is unfortunate that
the fourth column cannot be used, because the declaration a non-expert
would naturally use would be that in the second row.
Sources: 2018 edition, 2004 edition.