Array-Index und argc Signedness
Frage
Der C Standard (< strong> 5.1.2.2.1 Programmstart ) sagt:
Die Funktion beim Programmstart aufgerufen heißt main. [...]
Es ist de fi niert mit einem Rückgabetyp int und ohne Parameter:
int main(void) { /* ... */ }
oder mit zwei Parametern [...] :
int main(int argc, char *argv[]) { /* ... */ }
Und später sagt:
Der Wert von argc soll nicht negativ sein.
- Warum nicht
argc
alsunsigned int
definiert werden,argc
angeblich bedeutet 'Argument count'? - Should
argc
als Index fürargv
verwendet werden?
So begann ich mich gefragt, ob der C-Standard etwas über die Art des Array-Index sagt. Ist es unterzeichnet?
6.5.2.1 Array Subskribierung :
Einer der Begriffe sind Typ haben ‚‚ Zeiger auf Objekttyp ‘‘, die andere dieser Begriff hat Integer-Typen , und das Ergebnis hat Typ ‚‚ type ‘‘.
Es sagt nichts über seine Signedness (oder ich habe es nicht finden). Es ist ziemlich häufig Codes zu sehen Negative Array-Indizes (array[-1]
) verwenden, aber ist es nicht Verhalten nicht definiert?
- Should Arrays Indizes ohne Vorzeichen sein?
Lösung
Der Grund für die int in main () ist historisch - es ist schon immer so, seit lange vor der Sprache standardisiert wurde. Die Anforderung eines Array-Index ist, dass es innerhalb der Grenzen des Arrays ist (oder in einigen Fällen eine über das Ende.) - alles andere ist nicht definiert, so dass die Signedness immateriell ist
Andere Tipps
1) Über main () argc Typ: IMHO weiterhin der Standard eine sehr alte Tradition (mehr als 30 Jahre), und jetzt ... es ist einfach zu spät zu ändern Dinge (Anmerkung: auf den meisten Systemen weder den Compiler, noch der Linker, noch die CPU wird sich beschweren, wenn „arge“ definiert ist „unsigned“, aber Sie sind aus dem Standard!)
2) Bei den meisten Implementierungen argv [argc] ist legal und wird auf NULL. Tatsächlich ist eine alternative Art und Weise das Ende der Argumentliste zu finden ist, zu iterieren auf argv von 0 endet, wenn argv [i] NULL ist.
3) Array / Zeigerarithmetik mit negativen Zahlen ist legal, so weit wie der Adressbereich von (p-n) bis p zu demselben Speicherobjekt gehört. I.E. Sie können haben
char array[100];
char *p;
p = &array[50];
p += -30; /* Now p points to array[20]. */
Diese Verwendung von Zeigerarithmetik ist legal, da die resultierenden Zeiger noch in dem ursprünglichen Speicherobjekt bleibt ( „Array“). Auf den meist System kann die Zeigerarithmetik verwendet werden, bei Verstoß gegen diese Regel im Speicher zu navigieren, aber das ist nicht tragbar, da es vollständig systemabhängig ist.
In der Regel in C, das „Prinzip der geringsten Überraschung“ impliziert, dass es vorzuziehen ist, eine Variable unterzeichnet zu machen, es sei denn es einen guten Grund ist für sie ohne Vorzeichen zu sein. Dies liegt daran, dass die Art-Förderung Regeln zu unerwarteten Ergebnissen führen können, wenn Sie und Werte ohne Vorzeichen unterzeichnet mischen: zum Beispiel, wenn argc
unsigned wurde dann dieser einfache Vergleich zu überraschenden Ergebnissen führen würden:
if (argc > -1)
(Der -1
zu unsigned int
gefördert wird, so dass ihr Wert auf UINT_MAX
umgewandelt wird, die mit ziemlicher Sicherheit größer als argc
).
1) ARGC ist ein Argument zählen, aber ganz ehrlich zu sein, wie kann man ein Argument vor dem Programmnamen, der argv[0]
voranstellen. Stellen Sie sich ein Programm namens foo
, kann man nicht einfach sagen args1 foo args2
wie sinnlos ist, trotz der argc
ein signiertes Art von int
zu sein, das heißt nicht so etwas wie argv[-1]
, die Sie ‚args1‘ ...
2) Der Grund argc ist nicht wirklich ein Index für das Argument Vektor (also ‚ argv ‘) als die Laufzeit des ausführbaren Programmnamen in der stopft nullten Offset, dh argv[0]
daher die argc
von 1 aus sein wird.
3) Array-Indizes in Bezug auf die Zeigermanipulation, zur Verfügung gestellt Sie sind innerhalb der Grenzen des Blocks des Speichers, wo der Zeiger auf ist, Array-Indizes als negativ mit legal ist, da der Array-Indizes eine Abkürzung für die Zeiger ist, und nicht allein das, sie sind kommutativ zB
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';
Auch wenn Sie verwenden und manipulieren Arrays in einer solchen Art und Weise, die außerhalb der Grenzen ist - das nicht definiertes Verhalten ist und hängt von der Umsetzung der Laufzeit, wie man es handhaben, vielleicht ein Segmentierungsfehler, oder ein Programm Absturz ....
4) In * nix-Umgebungen, müssten einige einen dritten Parameter Haupt char **endvp
geliefert wird, wieder das selten in der Microsoft-Welt von DOS / Windows verwendet wird. Einige * nichts Laufzeitimplementierungen für prähistorische Gründe Sie in den Umgebungsvariablen über die Laufzeit passieren könnten.