int main( const int argc , const char[] const argv)
Ponieważ w efektywnym punkcie C ++ nr 3 napisano: „Używaj stałej zawsze, gdy jest to możliwe”, zaczynam się zastanawiać „dlaczego nie uczynić tych„ stałych ”parametrów const
?
Czy istnieje scenariusz, w którym wartość argc
jest modyfikowana w programie?
argc
jakoconst
.--argc
const
; faktycznie, przekazanieargc
jakoconst int
środek, którego nie można następnie użyćargc
jako, powiedzmy, licznika wewnątrz funkcji.const
parametr przekazujący wartość. Patrz np stackoverflow.com/a/8714278/277304 i stackoverflow.com/a/117557/277304Odpowiedzi:
W tym przypadku liczy się historia. C zdefiniował te dane wejściowe jako „niestałe”, a zgodność z (znaczną częścią) istniejącego kodu C była wczesnym celem C ++.
Niektóre interfejsy API UNIX, takie jak
getopt
, faktycznie manipulująargv[]
, więc nie można tego zrobić równieżconst
z tego powodu.(Na bok: Co ciekawe, chociaż
getopt
prototyp sugeruje, że nie modyfikuje,argv[]
ale może modyfikować wskazywane łańcuchy, strona podręcznika Linux wskazuje, żegetopt
permutuje swoje argumenty i wygląda na to, że wiedzą, że są niegrzeczni . Strona podręcznika podręcznika Open Grupa nie wspomina o tej permutacji).Umieszczenie
const
naargc
iargv
nie kupić dużo, i byłoby unieważnienie trochę starej szkoły programowania praktyki, takie jak:Pisałem takie programy w C i wiem, że nie jestem sam. Skopiowałem przykład skądś .
źródło
const
doargv
, bez wpływu na to, co każdy może zrobić funkcja C. Ponadtogetopt
jest deklarowany jakoint getopt(int argc, char * const argv[], const char *optstring);
. I tutajconst
nie jest to najwyższy poziom, ale deklaruje, że wskaźniki sąconst
, obietnica ich nie modyfikowania (chociaż łańcuchy, na które wskazują, mogą zostać zmodyfikowane).char* const* ___argv
tam jest, ale interfejs faktycznie do niego pasujeconst char **
. Takie zamieszanie. Pomyliłem pierwszeństwo[]
i w*
odniesieniu doconst
. Przepraszam.getopt()
wie, że nie przestrzega standardu, ponieważ zwraca uwagę naPOSIXLY_CORRECT
zmienną środowiskową, aby działała poprawnie. W szczególności POSIX nie przesuwa argumentów i nie szuka opcji po pierwszym argumencie niebędącym opcją.Norma C (ISO / IEC 9899: 2011) mówi:
Zwróć uwagę na ostatni punkt. Mówi, że oba
argc
iargv
powinny być modyfikowalne. Nie trzeba ich modyfikować, ale można je modyfikować.źródło
QApplication(argc,argv)
konstruktor Qt został zdefiniowanyargc
przez odniesienie . To mnie zaskoczyło.argc
zwykle nie jest stałą, ponieważ sygnatura funkcji dlamain()
dat poprzedzającychconst
.Ponieważ argc jest zmienną stosową, zmiana jej nie wpłynie na nic poza twoim własnym przetwarzaniem w linii poleceń.
Oczywiście możesz to zadeklarować,
const
jeśli chcesz.źródło
Najwyższy poziom
const
argumentu formalnego nie jest częścią typu funkcji. Możesz go dodać lub usunąć, jak chcesz: wpływa tylko na to, co możesz zrobić z argumentem w implementacji funkcji.Więc dla
argc
można dodać dowolnie dodaćconst
.Ale
argv
nie możesz zrobić danych znakuconst
bez zmiany sygnatury funkcji. Co oznacza, że nie jest to jeden ze standardowychmain
sygnatur funkcji i nie będzie musiał być rozpoznawany jakomain
funkcja. Więc to nie jest dobry pomysł.Dobrym powodem niestosowania
main
argumentów standardowych w programach innych niż zabawki jest to, że w systemie Windows nie są one w stanie przedstawić rzeczywistych argumentów programów, takich jak nazwy plików ze znakami międzynarodowymi. Dzieje się tak dlatego, że w systemie Windows są one według bardzo silnej konwencji kodowane jako Windows ANSI. W systemie Windows można zaimplementować bardziej przenośne narzędzie dostępu do argumentów w zakresieGetCommandLine
funkcji API.Podsumowując, nic nie stoi na przeszkodzie,
const
aby dodać doargc
, ale najbardziej użytecznaconst
funkcjaargv
daje niestandardowąmain
funkcję, prawdopodobnie nie rozpoznawaną jako taką. Na szczęście (w ironiczny sposób) istnieją dobre powody, aby nie używać standardowychmain
argumentów dla przenośnego, poważnego kodu. Po prostu, w praktyce obsługują tylko stare ASCII, tylko z literami alfabetu angielskiego.źródło
main
podpis działa dobrze i możesz otrzymywać dowolne argumenty Unicode.Podpis
main
jest czymś w rodzaju historycznego artefaktu zC
. HistorycznieC
nie miałconst
.Możesz jednak zadeklarować swój parametr,
const
ponieważ efekty const dotyczą tylko czasu kompilacji.źródło
const
został dodany do C89 / C90; wcześniej nie był częścią C.Ponieważ
argc
jest to zmienna lokalna (aw C ++ nie jest to odniesienie ani coś w tym rodzaju), a specjalne miejscemain
oznacza, że shenanigans wstecznej kompatybilności daje jej ogromną swobodę bez żadnego istotnego powodu, aby wymusić na aplikacjach, aby stała się stała.te i wiele innych odmian będzie kompilowanych na wielu kompilatorach C i C ++.
Więc ostatecznie nie chodzi o to, że argc nie jest const, po prostu nie musi tak być, ale może tak być, jeśli chcesz, aby tak było.
http://ideone.com/FKldHF , przykład w C:
http://ideone.com/m1qc9c , przykład w C ++
źródło
-std=c++11
. Clang również go akceptuje, ale dajewarning: only one parameter on 'main' declaration [-Wmain]
, a MSVC protestuje tylko o brakującym specyfikatorze typu zwracanego i braku odniesienia do argc. Ponownie, 'shenanigans' i 'leeway' :)Oprócz powodów historycznych, dobrym powodem, aby zachować argumenty argc i argv non-,
const
jest to, że implementacja kompilatora nie wie, co zrobisz z argumentami main, po prostu wie, że musi podać te argumenty.Definiując własne funkcje i skojarzone z nimi prototypy, wiesz, jakie parametry możesz wprowadzić,
const
a które funkcja będzie modyfikować.W skrajnym przypadku można zadeklarować, że wszystkie parametry wszystkich funkcji powinny być zadeklarowane
const
, a wtedy gdybyś miał powód, aby je zmienić (np. Zmniejszyć indeks, aby przeszukać tablicę), musiałbyś utworzyć lokalneconst
zmienne niezmienne i skopiuj wartościconst
argumentów do tych zmiennych. To sprawia, że praca jest zajęta i ma dodatkowe LOC, bez realnych korzyści. Przyzwoity analizator statyczny podniesie się, jeśli nie zmodyfikujesz wartości argumentu i zalecisz utworzenie parametruconst
.źródło