(пытаясь сосредоточиться на других аспектах вопроса)
Практическое правило для объявлений const заключается в чтении их справа налево, а const
изменяет следующий токен. Исключение: в начале объявления const
изменяет предыдущий токен.
За этим исключением стоит обоснование - для элементарных объявлений const char c
выглядит для некоторых людей более естественных, чем char const c
- и сообщается, что форма предшественника const char c
предшествует окончательному константному править.
Getopt
int getopt(int argc, char * const argv[], const char *optstring);
или
int getopt(int argc, char * const * argv, const char *optstring);
Это означает, что argv
является указателем на константный вектор указателей на неконстантные строки.
Но можно ожидать следующего объявления:
int getopt(int argc, char const * const * argv, const char *optstring);
(указатель на константный вектор для константных строк)
Потому что getopt()
не должен изменять строки, на которые ссылается argv.
Как минимум char **
(как используется в main()
) автоматически преобразуется в char * const * argv
.
Clang
ASTUnit::LoadFromCommandLine(..., const char **argv, ...);
Это означает, что argv
является указателем на неконстантный массив указателей на константные строки.
Опять можно ожидать const char * const *argv
по той же причине, что и выше.
Но это более заметно, поскольку char **
не преобразует в const char **
, например,
int main(int argc, char **argv) {
const char **x = argv; // Compile error!
return 0;
}
выдает ошибку компиляции, где
int main(int argc, char **argv) {
char * const *x = argv;
return 0;
}
и
int main(int argc, char **argv) {
const char * const *x = argv;
return 0;
}
нет.