Dlaczego argc nie jest stałą?
int main( const int argc , const char[] const argv)
Jako że efektywny C++ Punkt#3 stwierdza "użyj const, gdy tylko jest to możliwe", zaczynam myśleć "dlaczego nie wprowadzić tych 'stałych' parametrów const
"?.
Czy Jest jakiś scenariusz, w którym wartość argc
jest modyfikowana w programie?
7 answers
W tym przypadku historia jest czynnikiem. C zdefiniował te wejścia jako "nie stałe" , a kompatybilność z (sporą częścią) istniejącego kodu C była wczesnym Celem C++.
Niektóre uniksowe API, takie jak getopt
, w rzeczywistości manipulują argv[]
, więc nie można ich stworzyć const
również z tego powodu.
(pomijając: co ciekawe, chociaż prototyp getopt
sugeruje, że nie zmodyfikuje argv[]
, ale może zmodyfikować wskazywane ciągi znaków, strona podręcznika Linuksa wskazuje, że getopt
permutuje swoje argumenty, i wygląda na to, że wiedzą, że są niegrzeczni. Strona podręcznika w grupie otwartej nie wspomina o tej permutacji.)
Umieszczenie const
na argc
i argv
nie kupiłoby wiele i unieważniłoby niektóre stare praktyki programowania, takie jak:
// print out all the arguments:
while (--argc)
std::cout << *++argv << std::endl;
Pisałem takie programy w C i Wiem, że nie jestem sam. Skopiowałem przykład z gdzieś .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 04:55:09
Standard C (ISO / IEC 9899:2011) mówi:
5.1.2.2.1 uruchamianie programu
¶1 funkcja wywoływana podczas uruchamiania programu nosi nazwę
main
. Realizacja deklaruje nie prototyp dla tej funkcji. Definiuje się go za pomocą typu zwrotnego int i bez parametry:int main(void) { /* ... */ }
Lub z dwoma parametrami (zwanymi tutaj
argc
iargv
, choć dowolne nazwy mogą być używane, ponieważ są lokalne do funkcji, w której są "zadeklarowana"): {]}int main(int argc, char *argv[]) { /* ... */ }
Lub równoważne;10) lub w inny sposób określony w implementacji.
¶2 jeśli są zadeklarowane, parametry funkcji
main
są następujące ograniczenia:
- wartość
argc
jest nonnegatywna.argv[argc]
jest wskaźnikiem zerowym.- jeśli wartość {[3] } jest większa od zera, to członkowie tablicy
argv[0]
poprzezargv[argc-1]
inclusive zawiera wskaźniki do łańcuchów, które są podano implementacja - zdefiniowane wartości przez środowisko hosta przed uruchomieniem programu. Na intencją jest dostarczenie do programu informacji określonych przed uruchomieniem programu z innego miejsca w środowisku hostowanym. Jeśli środowisko hosta nie jest w stanie dostarczanie ciągów z literami zarówno wielkimi, jak i małymi literami, implementacja zapewnia, że ciągi są odbierane małymi literami.- jeśli wartość
argc
jest większa od zera, łańcuch wskazywany przezargv[0]
reprezentuje nazwę programu;argv[0][0]
jest znakiem null, jeśli nazwa programu nie jest dostępna w środowisku hosta. Jeśli wartośćargc
jest więcej niż jeden, ciągi wskazywane przezargv[1]
przezargv[argc-1]
reprezentują parametry programu.- parametry
argc
iargv
oraz łańcuchy wskazywane przez tablicęargv
powinny mogą być modyfikowane przez program i zachowują swoje ostatnio zapisane wartości między programem uruchomienie i zakończenie programu.10) Tak więc,
int
można zastąpić nazwą typedef zdefiniowaną jakoint
, lub typargv
można zapisać jakochar **argv
, i tak dalej.
Zwróć uwagę na ostatni punkt. Mówi, że zarówno argc
jak i argv
powinny być modyfikowalne. Nie muszą być modyfikowane, ale mogą być modyfikowane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 03:25:19
argc
zwykle nie jest stałą, ponieważ podpis funkcji main()
przed datami const
.
Ponieważ argc jest zmienną stosu, zmiana nie wpłynie na nic innego niż własne przetwarzanie wiersza poleceń.
Oczywiście możesz to zadeklarować, jeśli chcesz.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 03:19:30
Najwyższy poziom const
Na argumencie formalnym 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 dodawać dowolnie const
.
Ale dla argv
nie można utworzyć danych znakowych const
bez zmiany podpisu funkcji. Oznacza to, że nie jest to jeden ze standardowych podpisów funkcji main
i nie będzie musiał być rozpoznawany jako main
Funkcja. To nie jest dobry pomysł.
Dobrym powodem nieużywania standardowych argumentów main
w programach innych niż toy jest to, że w Windows nie są one w stanie reprezentować rzeczywistych argumentów programu, takich jak nazwy plików ze znakami międzynarodowymi. To dlatego, że w Windows są one przez bardzo silną konwencję zakodowane jako Windows ANSI. W systemie Windows można zaimplementować nieco bardziej przenośny argument access facility pod względem funkcji API GetCommandLine
.
Podsumowując, nic zapobiega dodawaniu const
do argc
, ale najbardziej użyteczne const
-ness na argv
da ci niestandardową funkcję main
, najprawdopodobniej nie rozpoznaną jako taka. Na szczęście (w ironiczny sposób) istnieją dobre powody, aby nie używać standardowych argumentów main
dla portable serious code. Po prostu, w praktyce obsługują tylko stare ASCII, tylko z literami alfabetu angielskiego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 04:23:31
Podpis main
jest w pewnym sensie historycznym artefaktem z C
. Historycznie C
nie miał const
.
Możesz jednak zadeklarować swój parametr const
, ponieważ efekty const to tylko czas kompilacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 03:13:42
Ponieważ argc
jest zmienną lokalną (a w C++ nie referencją czy czymś takim), a ponieważ specjalne miejsce main
oznacza, że wsteczna kompatybilność daje jej ogromną swobodę bez przekonującego powodu, aby wymusić aplikacje, aby uczynić ją const.
main() {}
int main() {}
main() { return 0; }
main(int argc, char* argv[]) { return 0; }
int main(const int argc, const char** argv) { /* no return*/ }
Te i wiele innych odmian kompiluje się na szerokiej gamie kompilatorów C i C++.
Więc ostatecznie nie jest tak, że argc nie jest const, tylko, że nie musi być, ale może być, jeśli chcę, żeby tak było.
Http://ideone.com/FKldHF, C przykład:
main(const int argc, const char* argv[]) { return 0; }
Http://ideone.com/m1qc9c, C++ przykład
main(const int argc) {}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 05:50:43
Poza historycznymi powodami, dobrym powodem, aby zachować argc i argv non-const
jest to, że implementacja kompilatora nie wie, co zamierzasz zrobić z argumentami do main, wie tylko, że musi podać te argumenty.
Kiedy definiujesz własne funkcje i powiązane z nimi prototypy, wiesz, które parametry możesz wykonać const
i które z nich zmodyfikuje twoja funkcja.
Wzięte do ekstremum, Można zadeklarować, że wszystkie parametry do wszystkich funkcji należy zadeklarować const
, a następnie, jeśli masz powód, aby je zmienić (np. zmniejszyć indeks, aby przeszukiwać tablicę), musisz utworzyć lokalne zmienne Nie-const
i skopiować wartości argumentów const
do tych zmiennych. To sprawia, że praca i dodatkowe LOC bez realnych korzyści. Przyzwoity analizator statyczny wykryje, jeśli nie modyfikujesz wartości argumentu i zaleci utworzenie parametru const
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 19:32:27