2010-03-14 17 views
6

El C standard (5.1.2.2.1 Programa de inicio) dice:de índice de matriz y argc de signo

La función llamada al inicio del programa se denomina principal. [...]
os será de fi nido con un tipo de retorno de int y sin parámetros:
int main(void) { /* ... */ }

o con dos parámetros [...]:
int main(int argc, char *argv[]) { /* ... */ }

Y más adelante dice:

El valor de argc no será negativo.

  • ¿Por qué no debería argc ser definido como un unsigned int, argc supuestamente significa 'número de argumentos'?
  • ¿Debería usarse argc como índice para argv?

Así que comencé a preguntarme si el estándar C dice algo sobre el tipo de índice de la matriz. ¿Está firmado?

6.5.2.1 Matriz subscripting:

Una de las expresiones tendrán tipo '' puntero a tipo de objeto '', el otro expresión tendrá número entero tipo, y el resultado tiene el tipo '' tipo ''.

No dice nada sobre su firma (o no lo encontré). Es bastante común ver códigos que usan índices de matriz negativos (array[-1]), pero ¿no es un comportamiento indefinido?

  • ¿Deben los índices de la matriz ser unsigned?
+0

Simplemente declare que no tiene firma, nada malo sucederá. En realidad se llama con 3 argumentos, puede agregar char * env []. –

+0

@nobugz, sí, sé que no pasará nada malo, me preguntaba por qué 'argc' está firmado de acuerdo con el estándar. 'char * envp []' depende de la plataforma y 'char * apple []' está en MacOSX/Darwin. –

+0

Esta pregunta es un duplicado de http: // stackoverflow.com/questions/1773897/why-is-argc-an-int-rather-an-unsigned-int – caf

Respuesta

6

El motivo de la int en main() es histórico, siempre ha sido así, desde mucho antes de que el lenguaje estuviera estandarizado. El requisito de un índice de matriz es que esté dentro de los límites de la matriz (o en algunas circunstancias, uno más allá del final); cualquier otra cosa no está definida, por lo que la firma no es importante.

3

1) Acerca de main() argc type: En mi humilde opinión el estándar continúa una tradición muy antigua (más de 30 años!), Y ahora ... es demasiado tarde para cambiar las cosas (NOTA: en la mayoría de los sistemas ni el compilador , ni el enlazador, ni la CPU se quejarán si "argc" se define como "sin firmar", ¡pero estás fuera del estándar!)

2) En la mayoría de las implementaciones argv [argc] es legal y se evalúa como NULL. De hecho, una forma alternativa de encontrar el final de la lista de argumentos es iterar en argv desde 0 terminando cuando argv [i] es NULL.

3) La aritmética de matriz/puntero con números negativos es legal en la medida en que el rango de direcciones de (p-n) a p pertenece al mismo objeto de memoria. ES DECIR. usted puede tener

char array[100]; 
char *p; 

p = &array[50]; 
p += -30; /* Now p points to array[20]. */ 

Este uso de la aritmética de punteros es legal porque el puntero resultante todavía permanece dentro del objeto de memoria original ("array"). En la mayoría de los sistemas, la aritmética del puntero se puede utilizar para navegar en la memoria en violación de esta regla, pero esto NO es portátil, ya que depende completamente del sistema.

+2

Tener argv [argc] NULL es obligatorio por el estándar. – AProgrammer

-2

1) Argc es un recuento de argumentos, pero para ser honesto, ¿cómo se puede anteponer un argumento ante el nombre del programa que argv[0]. Imagine un programa llamado foo, no se puede simplemente decir args1 foo args2 ya que es sin sentido, a pesar de la argc ser un tipo con signo de int, es decir, no existe tal cosa como argv[-1] que le llevará 'args1' ...

2) La razón argc no es realmente un índice para el vector de argumento (de ahí 'argv') como el tiempo de ejecución mete el nombre del programa ejecutable en el zero'th compensación, es decir argv[0] de ahí el argc habrá fuera por 1.

3) Indices de matriz, en términos de manipulación del puntero, proporcionado usted está dentro de los límites del bloque de memoria donde está el puntero, usando subíndices de matriz como negativo es legal ya que los subíndices de matriz son un atajo para los punteros, y no solo eso, son conmutativos, p.

 
char v[100]; 
char *p = &v[0]; 

You can do this: 

p[55] = 'a'; 

Which is the same as 

*(p + 55) = 'a'; 

You can even do this: 

p = &v[55]; 

p[-10] = 'b' /* This will stuff 'b' into 45'th offset! */ 

Which is the same as 

*(p - 10) = 'b'; 

Además, si utiliza matrices y manipularlas de tal manera que se encuentra fuera de los límites - que es un comportamiento indefinido y dependerá de la implementación del tiempo de ejecución sobre cómo manejar la situación, tal vez un fallo de segmentación , o un bloqueo del programa ....

4) En entornos * nix, algunos tendrían un tercer parámetro suministrado al char **endvp principal, de nuevo, esto rara vez se utiliza en el mundo de Microsoft de DOS/Windows. Algunas implementaciones de tiempo de ejecución * nix, por razones prehistóricas, puede pasar las variables de entorno durante el tiempo de ejecución.

+0

1) Le pregunté por qué 'argc' no está sin signo en el estándar, no si pudiera usar índices negativos. 2) Mi segunda pregunta fue la relación entre la firma de 'argc' y la firma del índice de una matriz (también conocido como el parámetro del operador []). 4) Lo sé, pero no está escrito en el estándar. –

3

En general, en C, el "principio de menor sorpresa" implica que es preferible hacer una variable firmada a menos que haya una buena razón para que no esté firmada. Esto se debe a que las reglas de promoción de tipo pueden conducir a resultados inesperados cuando se mezcla firmado y valores sin signo: por ejemplo, si argc fue sin firmar a continuación, esta simple comparación conduciría a resultados sorprendentes:

if (argc > -1) 

(se promueve la -1 a unsigned int, por lo que su valor se convierte en UINT_MAX, que es casi seguro mayor que argc).

+0

Esa es una forma interesante de explicarlo. –

Cuestiones relacionadas