Take e.g. execve(2), which according to posix has this prototype [1]:
int execve(const char *path, char *const argv[], char *const envp[]);
To me, it seems as if
int execve(const char *path, const char *const argv[], const char *const envp[]);
would have been an obvious improvement.
So, does anyone know why this is as it is? What can explain the need to possibly manipulate the given argv/envp strings?
[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
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[]
andenvp[]
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 theargv[]
andenvp[]
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
orenvp
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With