int main( const int argc , const char[] const argv)
Como el artículo n. ° 3 de C ++ efectivo dice "Use const siempre que sea posible", empiezo a pensar "¿por qué no hacer estos parámetros 'constantes' const
"?
¿Existe algún escenario en el que argc
se modifique el valor de en un programa?
argc
comoconst
.--argc
const
; de hecho, pasarargc
como unconst int
medio que luego no puede usarargc
como, digamos, un contador dentro de la función.const
un parámetro de paso por valor. Ver, por ejemplo, stackoverflow.com/a/8714278/277304 y stackoverflow.com/a/117557/277304Respuestas:
En este caso, la historia es un factor. C definió estas entradas como "no constantes", y la compatibilidad con (una buena parte del) código C existente fue uno de los primeros objetivos de C ++.
Algunas API de UNIX, como
getopt
, en realidad manipulanargv[]
, por lo que no se pueden crear tambiénconst
por esa razón.(Aparte: Curiosamente, aunque
getopt
el prototipo sugiere que no modificaráargv[]
pero puede modificar las cadenas señaladas, la página de manual de Linux indica quegetopt
permuta sus argumentos, y parece que saben que están siendo traviesos . La página de manual de Open Group no menciona esta permutación).Poniendo
const
enargc
yargv
no comprar mucho, y sería invalidar algunos de la vieja escuela prácticas de programación, tales como:He escrito este tipo de programas en C y sé que no estoy solo. Copié el ejemplo de alguna parte .
fuente
const
aargv
, sin afectar lo que puede hacer cualquier función C. Además,getopt
se declara comoint getopt(int argc, char * const argv[], const char *optstring);
. Y aquíconst
no es el nivel superior, pero declara que los punteros sonconst
, una promesa de no modificarlos (aunque las cadenas a las que apuntan posiblemente se modifiquen).getopt
permuta laargv[]
matriz por defecto, pero no modifica las cadenas. (La palabra permute viene directamente de la página del manual). Eso significa que laargv
matriz en sí no esconst
incluso si las cadenas a las que apunta lo son. ¿Cómo permutar laargv[]
matriz no manipularla?char* const* ___argv
ahí, pero la interfaz realmente se adhiereconst char **
. Tanta confusión. Había confundido la precedencia de the[]
y the*
con respecto a theconst
. Mis disculpas.El estándar C (ISO / IEC 9899: 2011) dice:
Tenga en cuenta la última viñeta. Dice que ambos
argc
yargv
deberían ser modificables. No es necesario modificarlos, pero pueden modificarse.fuente
QApplication(argc,argv)
constructor de Qt se definió conargc
por referencia . Eso me sorprendió.argc
normalmente no es una constante porque la firma de función paramain()
fechas anterioresconst
.Dado que argc es una variable de pila, cambiarla no afectará a nada más que a su propio procesamiento de línea de comando.
Por supuesto,
const
eres libre de declararlo si quieres.fuente
Un nivel superior
const
en un argumento formal no es parte del tipo de función. Puede agregarlo o eliminarlo como desee: solo afecta lo que puede hacer con el argumento en la implementación de la función.Entonces, para
argc
que pueda agregar libremente, agregue un archivoconst
.Pero
argv
no se pueden hacer los datos del carácterconst
sin cambiar la firma de la función. Lo que significa que entonces no es una de lasmain
firmas de función estándar y no tendrá que ser reconocida como unamain
función. Entonces, no es una buena idea.Una buena razón para no usar los
main
argumentos estándar en programas que no son de juguete es que en Windows no pueden representar los argumentos reales del programa, como los nombres de archivo con caracteres internacionales. Eso es porque en Windows están codificados por convención muy fuerte como Windows ANSI. En Windows, puede implementar algunasGetCommandLine
funciones de acceso a argumentos más portátiles en términos de la función API.En resumen, nada impide que se agreguen
const
aargc
, pero el más útilconst
-ness enargv
que le daría un no-estándar demain
la función, la mayoría probablemente no reconocido como tal. Afortunadamente (de manera irónica) hay buenas razones para no usar losmain
argumentos estándar para código serio portátil. En pocas palabras, para la práctica solo admiten el antiguo ASCII, con solo letras del alfabeto inglés.fuente
main
firma estándar funciona bien y usted puede recibir argumentos Unicode arbitrarios.La firma de
main
es algo así como un artefacto histórico deC
. HistóricamenteC
no lo teníaconst
.Sin embargo, puede declarar su parámetro
const
ya que los efectos de const son solo en tiempo de compilación.fuente
const
se añadió a C89 / C90; antes de eso, no era parte de C.Porque
argc
es una variable local (y, en C ++, no una referencia o algo así), y porque el lugar especial demain
significa que los chanchullos de compatibilidad con versiones anteriores le otorgan una gran cantidad de libertad sin ninguna razón convincente para forzar a las aplicaciones a hacerla constante.estas y muchas otras variaciones se compilarán en una amplia gama de compiladores C y C ++.
Entonces, en última instancia, no es que argc no sea constante, solo que no tiene que serlo, pero puede serlo si quieres que lo sea.
http://ideone.com/FKldHF , ejemplo de C:
http://ideone.com/m1qc9c , ejemplo de C ++
fuente
-std=c++11
. Clang también lo acepta pero cedewarning: only one parameter on 'main' declaration [-Wmain]
, y MSVC solo protesta por el especificador de tipo de retorno que falta y la falta de una referencia a argc. Nuevamente, 'travesuras' y 'libertad deAparte de las razones históricas, una buena razón para mantener argc y argv non-
const
es que la implementación del compilador no sabe qué vas a hacer con los argumentos de main, solo sabe que debe darte esos argumentos.Cuando está definiendo sus propias funciones y prototipos asociados, sabe qué parámetros puede hacer
const
y cuáles modificará su función.Llevado al extremo, podría declarar que todos los parámetros de todas las funciones deben declararse
const
, y luego, si tuviera una razón para cambiarlos (por ejemplo, disminuir un índice para buscar en una matriz), tendría que hacer que no seanconst
variables locales y copie losconst
valores de los argumentos en esas variables. Eso lo convierte en un trabajo ajetreado y un LOC adicional sin ningún beneficio real. Un analizador estático decente se activará si no está modificando el valor de un argumento y le recomendará que cree el parámetroconst
.fuente