int main( const int argc , const char[] const argv)
Como Effective C ++ Item # 3 afirma "Use const sempre que possível", eu começo a pensar "por que não fazer esses parâmetros 'constantes' const
"?
Existe algum cenário em que o valor de argc
é modificado em um programa?
argc
comoconst
.--argc
const
; na verdade, passarargc
como umconst int
meio que você não pode usarargc
como, digamos, um contador dentro da função.const
um parâmetro de passagem por valor. Consulte, por exemplo, stackoverflow.com/a/8714278/277304 e stackoverflow.com/a/117557/277304Respostas:
Nesse caso, a história é um fator. C definiu essas entradas como "não constantes" e a compatibilidade com (uma boa parte do) código C existente era um objetivo inicial do C ++.
Algumas APIs do UNIX, como
getopt
, realmente manipulamargv[]
, portanto, não podem ser feitasconst
por esse motivo também.(À parte: Curiosamente, embora
getopt
o protótipo de sugira que ele não irá modificar,argv[]
mas pode modificar as strings apontadas, a página do manual do Linux indica quegetopt
permuta seus argumentos, e parece que eles sabem que estão sendo malcriados . A página do manual no Open O grupo não menciona esta permutação.)Colocando
const
emargc
eargv
não comprar muito, e seria invalidar alguns old-school práticas, tais como a programação:Escrevi esses programas em C e sei que não estou sozinho. Copiei o exemplo de algum lugar .
fonte
const
aargv
, sem afetar o que qualquer função C pode fazer. Além disso,getopt
é declarado comoint getopt(int argc, char * const argv[], const char *optstring);
. E aqui oconst
não é o nível superior, mas declara que os ponteiros sãoconst
, uma promessa de não modificá-los (embora as strings para as quais eles apontam possam ser modificadas).char* const* ___argv
lá, mas a interface realmente adereconst char **
. Tanta confusão. Eu havia confundido a precedência do[]
e do*
com respeito aoconst
. Me desculpe.getopt()
sabe que não segue o padrão porque presta atenção àPOSIXLY_CORRECT
variável de ambiente para fazê-lo se comportar corretamente. Em particular, POSIX não permuta os argumentos e não procura opções após o primeiro argumento não opcional.O padrão C (ISO / IEC 9899: 2011) diz:
Observe o último marcador. Diz que ambos
argc
eargv
devem ser modificáveis. Eles não precisam ser modificados, mas podem ser modificados.fonte
QApplication(argc,argv)
construtor do Qt foi definido comargc
por referência . Isso me surpreendeu.argc
normalmente não é uma constante porque a assinatura da função paramain()
datas anterioresconst
.Visto que argc é uma variável de pilha, alterá-lo não afetará nada além do seu próprio processamento de linha de comando.
Você é, naturalmente, livre para declará-lo,
const
se quiser.fonte
Um nível superior
const
em um argumento formal não faz parte do tipo de função. Você pode adicioná-lo ou removê-lo como quiser: isso afeta apenas o que você pode fazer com o argumento na implementação da função.Portanto,
argc
você pode adicionar livremente umconst
.Mas para
argv
você não pode fazer os dados de caractereconst
sem, portanto, alterar a assinatura da função. O que significa que não é uma dasmain
assinaturas de função padrão e não terá que ser reconhecida como umamain
função. Portanto, não é uma boa ideia.Um bom motivo para não usar os
main
argumentos padrão em programas que não sejam de brinquedo é que no Windows eles não podem representar argumentos de programa reais, como nomes de arquivo com caracteres internacionais. Isso ocorre porque no Windows eles são codificados por convenção muito forte como Windows ANSI. No Windows, você pode implementar algum recurso de acesso de argumento mais portátil em termos daGetCommandLine
função API.Resumindo, nada impede que você adicione
const
aargc
, mas a maior utilidadeconst
emargv
forneceria umamain
função não padrão , muito provavelmente não reconhecida como tal. Felizmente (de uma forma irônica), há boas razões para não usar osmain
argumentos padrão para código sério portátil. Simplesmente, para a prática, eles suportam apenas ASCII antigo, com apenas letras do alfabeto inglês.fonte
main
assinatura padrão funciona bem e você pode receber argumentos Unicode arbitrários.A assinatura de
main
é uma espécie de artefato histórico deC
. HistoricamenteC
, nãoconst
.No entanto, você pode declarar seu parâmetro,
const
pois os efeitos de const são apenas em tempo de compilação.fonte
const
foi adicionado a C89 / C90; antes disso, não fazia parte de C.Porque
argc
é uma variável local (e, em C ++, não é uma referência ou algo assim), e porque o lugar especial demain
significa que as travessuras de compatibilidade com versões anteriores garantem a ele uma grande margem de manobra sem nenhuma razão convincente para forçar os aplicativos a torná-lo constante.essas e muitas outras variações serão compiladas em uma ampla variedade de compiladores C e C ++.
Portanto, em última análise, não é que argc não seja const, apenas que não precisa ser, mas pode ser, se você quiser.
http://ideone.com/FKldHF , exemplo C:
http://ideone.com/m1qc9c , exemplo C ++
fonte
-std=c++11
. O Clang também aceita, mas dáwarning: only one parameter on 'main' declaration [-Wmain]
, e o MSVC apenas protesta sobre o especificador de tipo de retorno ausente e a falta de uma referência a argc. Novamente, 'travessuras' e 'margem de manobra' :)Além das razões históricas, uma boa razão para manter argc e argv non-
const
é que a implementação do compilador não sabe o que você vai fazer com os argumentos de main, ela apenas sabe que deve fornecer esses argumentos.Quando você está definindo suas próprias funções e protótipos associados, você sabe quais parâmetros pode fazer
const
e quais sua função irá modificar.Levado ao extremo, você poderia declarar que todos os parâmetros para todas as funções deveriam ser declarados
const
, e então se você tivesse uma razão para alterá-los (por exemplo, diminuir um índice para pesquisar em um array), você teria que fazer nãoconst
variáveis locais e copie osconst
valores dos argumentos nessas variáveis. Isso torna o trabalho agitado e LOC extra sem nenhum benefício real. Um analisador estático decente pegará se você não estiver modificando o valor de um argumento e recomendará que você faça o parâmetroconst
.fonte