indice e argc signedness di Array
Domanda
Il C standard (< strong> 5.1.2.2.1 programma di avvio ) dice:
La funzione chiamata all'avvio del programma prende il nome principale. [...]
Sarà definita con un tipo di ritorno di int e senza Parametri:
int main(void) { /* ... */ }
o con due parametri [...] :
int main(int argc, char *argv[]) { /* ... */ }
E poi dice:
Il valore di argc deve essere non negativo.
- Perché non dovrebbe
argc
essere definito come ununsigned int
,argc
suppone che significa 'numero di argomenti'? - Nel caso
argc
essere utilizzato come indice perargv
?
Così ho iniziato a chiedermi se lo standard C dice qualcosa circa il tipo di indice di array. E 'firmato?
6.5.2.1 Array indicizzazione di :
Una delle espressioni avranno tipo ‘‘ puntatore al tipo di oggetto ’’, l'altra espressione deve avere tipo intero , e il risultato è di tipo ‘‘ tipo ’’.
Non dice nulla circa la sua signedness (o io non l'ho trovato). E 'abbastanza comune vedere i codici usando negativi indici di matrice (array[-1]
), ma non è che un comportamento indefinito?
- indici di matrice siano Qualora non firmato?
Soluzione
La ragione per l'int in main () è storica - è sempre stato così, da molto tempo prima la lingua è stata standardizzata. Il requisito di un indice di matrice è che è entro i limiti della matrice (o in alcuni casi, uno oltre la fine) -. Altro è definito, in modo che il signedness è irrilevante
Altri suggerimenti
1) A proposito di main () Tipo di argc: IMHO lo standard continua una tradizione molto antica (più di 30 anni), e ora ... è semplicemente troppo tardi per cambiare le cose (Attenzione: sulla maggior parte dei sistemi né il compilatore, né il linker, né la CPU si lamenterà se "argc" è definito "unsigned", ma si sono fuori dello standard!)
2) la maggior parte delle implementazioni argv [argc] è legale e restituisce NULL. In effetti, un modo alternativo per trovare alla fine della lista degli argomenti è quello di iterare sulle argv da 0 terminazione quando argv [i] è nullo.
3) Array / puntatori con numeri negativi è legale per quanto riguarda il settore degli indirizzi da (p-n) p appartiene allo stesso oggetto memoria. OSSIA si può avere
char array[100];
char *p;
p = &array[50];
p += -30; /* Now p points to array[20]. */
Questo utilizzo di aritmetica dei puntatori è legale perché il puntatore risultante rimane ancora dentro l'oggetto di memoria originale ( "allineamento"). Sulla maggior parte del sistema del l'aritmetica dei puntatori può essere utilizzato per navigare in memoria in violazione di questa regola, ma questo non è portabile in quanto è completamente dipendente dal sistema.
In generale in C, il "principio di minima sorpresa" implica che è preferibile fare una variabile firmato a meno che non ci sia una buona ragione per essere firmato. Questo perché le regole tipo di promozione può portare a risultati imprevisti quando si mescolano firmato e valori senza segno: per esempio, se argc
era firmato allora questo semplice confronto porterebbe a risultati sorprendenti:
if (argc > -1)
(La -1
è promosso a unsigned int
, quindi il suo valore viene convertito in UINT_MAX
, che è quasi certamente maggiore di argc
).
1) argc è un numero di argomenti, ma per essere onesti, come si può anteporre un argomento prima che il nome del programma che argv[0]
. Immaginate un programma chiamato foo
, non si può semplicemente dire args1 foo args2
come che è privo di significato, nonostante la argc
essere un tipo di firma int
, vale a dire una cosa come argv[-1]
che vi porterà 'args1' ...
2) La ragione argc non è realmente un indice al vettore argomento (da qui ' argv ') come runtime infila il nome del programma eseguibile nella zero'th offset, cioè argv[0]
quindi il argc
sarà off di 1.
3) indici di array, in termini di manipolazione dei puntatori, disponibile siete entro i confini del blocco di memoria in cui il puntatore si trova, con indici di matrice come negativo è giuridico dei indici di matrice sono una scorciatoia per i puntatori, e non solo quello, sono commutativa ad esempio
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';
Anche se si utilizza array e di manipolarli in modo tale che è al di fuori dei confini - che è un comportamento indefinito e dipenderà l'attuazione della fase di esecuzione su come gestire la cosa, forse un errore di segmentazione, o un programma di incidente ....
4) In ambienti * nix, qualcuno potrebbe avere un terzo parametro fornito al char **endvp
principale, ancora una volta questa è raramente utilizzato nel mondo Microsoft di DOS / Windows. Alcune implementazioni * nix run-time, per motivi preistorici, si potrebbe passare le variabili di ambiente tramite la fase di esecuzione.