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?

Author: Dinushan, 2013-12-13

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ś .

 112
Author: Joe Z,
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 i argv, 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] poprzez argv[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 przez argv[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 przez argv[1] przez argv[argc-1] reprezentują parametry programu.
  • parametry argc i argv 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ą jako int, lub typ argv można zapisać jako char **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.

 37
Author: Jonathan Leffler,
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.
 24
Author: razeh,
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.

 9
Author: Cheers and hth. - Alf,
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.

 5
Author: George,
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 mainoznacza, ż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) {}
 3
Author: kfsone,
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.

 1
Author: Sam Skuce,
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