¿Por qué argc no es una constante?


int main( const int argc , const char[] const argv)

Como C++efectivo El artículo#3 establece "Usar const siempre que sea posible", empiezo a pensar "¿por qué no hacer estos parámetros 'constantes' const"?.

¿Hay algún escenario en el que el valor de argc se modifique en un programa?

Author: Dinushan, 2013-12-13

7 answers

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 un objetivo temprano de C++.

Algunas API de UNIX, como getopt, en realidad manipulan argv[], por lo que no se puede hacer const por esa razón también.

(Aparte: Curiosamente, aunque el prototipo de getopt sugiere que no modificará argv[] sino que puede modificar las cadenas apuntadas, la página man de Linux indica que getopt permuta sus argumentos, y parece que saben que están siendo traviesos . La página de manual del Grupo Abierto no menciona esta permutación.)

Poner const en argc y argv no compraría mucho, e invalidaría algunas prácticas de programación de la vieja escuela, tales como:

// print out all the arguments:
while (--argc)
    std::cout << *++argv << std::endl;

He escrito tales programas en C, y sé que no estoy solo. Copié el ejemplo de en algún lugar.

 112
Author: Joe Z,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-13 04:55:09

El estándar C (ISO / IEC 9899:2011) dice:

5.1.2.2.1 Inicio del programa

¶1 La función llamada al inicio del programa se llama main. La aplicación declara no prototipo para esta función. Se definirá con un tipo de retorno de int y con no parámetros:

int main(void) { /* ... */ }

O con dos parámetros (referidos aquí como argc y argv, aunque cualquier nombre puede ser se utilizan, ya que son locales a la función en la que se declared):

int main(int argc, char *argv[]) { /* ... */ }

O equivalente;10) o de alguna otra manera definida por la implementación.

¶2 Si se declaran, los parámetros de la función main obedecerán lo siguiente limitaciones:

  • El valor de argc no será negativo.
  • argv[argc] será un puntero nulo.
  • Si el valor de argc es mayor que cero, los miembros de la matriz argv[0] a través de argv[argc-1] inclusive contendrá punteros a cadenas, que son dar valores definidos por el entorno host antes del inicio del programa. El la intención es proporcionar al programa información determinada antes del inicio del programa desde cualquier otro lugar del entorno alojado. Si el entorno host no es capaz de el suministro de cadenas con letras en mayúsculas y minúsculas, la implementación se asegurará de que las cadenas se reciban en minúsculas.
  • Si el valor de argc es mayor que cero, la cadena apuntada por argv[0] representa el nombre del programa; argv[0][0] será el carácter nulo si el nombre del programa no está disponible en el entorno host. Si el valor de argc es mayor que uno, las cadenas apuntadas por argv[1] hasta argv[argc-1] representar los parámetros del programa.
  • Los parámetros argc y argv y las cadenas apuntadas por la matriz argv deberán ser modificables por el programa, y conservar sus últimos valores almacenados entre el programa inicio y terminación del programa.

10) Así, int puede ser reemplazado por un nombre typedef definido como int, o el tipo de argv puede ser escrito como char **argv, y así sucesivamente.

Nótese el último punto. Dice que tanto argc como argv deben ser modificables. No tienen que ser modificados, pero pueden ser modificados.

 37
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-13 03:25:19

argc normalmente no es una constante porque la firma de función para main() es anterior a const.

Dado que argc es una variable de pila, cambiarla no afectará a nada más que su propio procesamiento de línea de comandos.

Usted es, por supuesto, libre de declararlo const si lo desea.

 24
Author: razeh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-13 03:19:30

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.

Así que para argc puede agregar libremente agregar un const.

Pero para argv no puede hacer que los datos de caracteres const sin cambiar la firma de la función. Lo que significa que entonces no es una de las firmas de función estándar main, y no tendrá que ser reconocida como una main función. Así que no es una buena idea.


Una buena razón para no usar los argumentos estándar main en programas que no son de juguete es que en Windows no son capaces de representar argumentos de programa reales como nombres de archivo con caracteres internacionales. Eso es porque en Windows son por convención muy fuerte codificado como ANSI de Windows. En Windows puede implementar alguna facilidad de acceso a argumentos más portátil en términos de la función API GetCommandLine.


Resumiendo, nada le impide agregar const a argc, pero la función const más útil en argv le daría una función main no estándar, probablemente no reconocida como tal. Felizmente (de una manera irónica) hay buenas razones para no usar los argumentos estándar main para portable serious code. Simplemente, para la práctica solo admiten ASCII antiguo, con solo letras del alfabeto inglés.

 9
Author: Cheers and hth. - Alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-13 04:23:31

La firma de main es algo así como un artefacto histórico de C. Históricamente C no tenía const.

Sin embargo, puede declarar su parámetro const ya que los efectos de const son solo en tiempo de compilación.

 5
Author: George,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-13 03:13:42

Porque argc es una variable local (y, en C++, no una referencia o algo así), y porque el lugar especial de main significa que las travesuras de compatibilidad hacia atrás le otorgan una gran cantidad de margen de maniobra sin ninguna razón convincente para forzar aplicaciones para que sea constante.

main() {}

int main() {}

main() { return 0; }

main(int argc, char* argv[]) { return 0; }

int main(const int argc, const char** argv) { /* no return*/ }

Estas y muchas otras variaciones se compilarán en una amplia gama de compiladores de C y C++.

Así que en última instancia, no es que argc no sea const, solo que no tiene que serlo, pero puede serlo si quiero que lo sea.

Http://ideone.com/FKldHF , C ejemplo:

main(const int argc, const char* argv[]) { return 0; }

Http://ideone.com/m1qc9c , ejemplo de C++

main(const int argc) {}
 3
Author: kfsone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-13 05:50:43

Aparte de las razones históricas, una buena razón para mantener argc y argv no-const es que la implementación del compilador no sabe lo que va a hacer con los argumentos de main, solo sabe que debe darle 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 a un extremo, podría declarar que todos los parámetros de todas las funciones debería declararse const, y luego si tuviera una razón para cambiarlas (por ejemplo, decrementar un índice para buscar a través de un array), tendría que hacer variables locales no-const y copiar los valores de los argumentos const en esas variables. Eso lo convierte en trabajo ocupado y LOC adicional sin ningún beneficio real. Un analizador estático decente captará si no está modificando el valor de un argumento, y le recomendará que cree el parámetro const.

 1
Author: Sam Skuce,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-13 19:32:27