Czy istnieje sposób określenia domyślnych argumentów funkcji w C?
c
arguments
default-parameters
Nathaniel Flath
źródło
źródło
Odpowiedzi:
Nie całkiem. Jedynym sposobem byłoby napisanie funkcji varargs i ręczne wpisanie wartości domyślnych dla argumentów, których nie wywołuje program wywołujący.
źródło
open(2)
Połączenia system wykorzystuje to dla opcjonalnego argumentu, które mogą być obecne w zależności od wymaganych argumentów iprintf(3)
odczytuje ciąg formatu, który określa ile argumenty nie będzie. Oba używają varargs dość bezpiecznie i skutecznie, i chociaż z pewnością można je zepsuć,printf()
szczególnie wydaje się dość popularne.Wow, wszyscy są tutaj takim pesymistą. Odpowiedź brzmi tak.
To nie jest trywialne: do końca będziemy mieli podstawową funkcję, strukturę wspierającą, funkcję otoki i makro wokół funkcji otoki. W mojej pracy mam zestaw makr do automatyzacji tego wszystkiego; kiedy zrozumiesz przepływ, będzie ci łatwo zrobić to samo.
Napisałem to gdzie indziej, więc tutaj jest szczegółowy zewnętrzny link do uzupełnienia podsumowania tutaj: http://modelingwithdata.org/arch/00000022.htm
Chcielibyśmy się odwrócić
w funkcję, która przyjmuje wartości domyślne (i = 8, x = 3,14). Zdefiniuj strukturę towarzyszącą:
Zmień nazwę swojej funkcji
f_base
i zdefiniuj funkcję otoki, która ustawia wartości domyślne i wywołuje bazę:Teraz dodaj makro, używając makr rozmaitości C. W ten sposób użytkownicy nie muszą wiedzieć, że faktycznie
f_args
wypełniają strukturę i myślą, że robią to, co zwykle:OK, teraz wszystkie następujące elementy będą działać:
Sprawdź reguły, w jaki sposób inicjalizatory złożone ustawiają wartości domyślne dla dokładnych reguł.
Jedna rzecz, która nie zadziała:
f(0)
ponieważ nie możemy odróżnić brakującej wartości od zera. Z mojego doświadczenia wynika, że jest to coś, na co należy uważać, ale można sobie z tym poradzić, gdy zajdzie taka potrzeba - połowa czasu, gdy domyślnie wynosi zero.Zadałem sobie trud napisania tego, ponieważ myślę, że nazwane argumenty i wartości domyślne naprawdę sprawiają, że kodowanie w C jest łatwiejsze i jeszcze przyjemniejsze. A C jest niesamowity, ponieważ jest tak prosty i wciąż ma wystarczająco dużo, aby wszystko to było możliwe.
źródło
{}
(pusty inicjator) to błąd C99.#define vrange(...) CALL(range,(param){.from=1, .to=100, .step=1, __VA_ARGS__})
Tak. :-) Ale nie w sposób, którego można by się spodziewać.
Niestety, C nie pozwala na przeciążanie metod, więc otrzymujesz dwie różne funkcje. Mimo to, wywołując f2, faktycznie dzwoniłbyś do f1 z wartością domyślną. Jest to rozwiązanie „Don't Repeat Yourself”, które pomaga uniknąć kopiowania / wklejania istniejącego kodu.
źródło
Możemy tworzyć funkcje, które używają nazwanych parametrów (tylko) dla wartości domyślnych. To kontynuacja odpowiedzi BK.
Standard C99 określa, że późniejsze nazwy w inicjalizacji zastępują poprzednie elementy. Możemy również mieć pewne standardowe parametry pozycyjne, wystarczy odpowiednio zmienić makro i podpis funkcji. Domyślnych parametrów wartości można używać tylko w nazwanym stylu parametrów.
Wyjście programu:
źródło
OpenCV używa czegoś takiego:
Jeśli użytkownik nie wie, co powinien napisać, ta sztuczka może być pomocna:
źródło
Nie.
Nie obsługuje tego nawet najnowszy standard C99.
źródło
Nie, to funkcja języka C ++.
źródło
Krótka odpowiedź: Nie.
Nieco dłuższa odpowiedź: istnieje stare, stare obejście, w którym przekazujesz ciąg, który analizujesz pod kątem opcjonalnych argumentów:
gdzie opt może zawierać parę „nazwa = wartość” lub coś, i jak byś nazwał
Oczywiście jest to przydatne tylko czasami. Zasadniczo, gdy chcesz mieć pojedynczy interfejs z rodziną funkcji.
Wciąż znajdziesz to podejście w kodach fizyki cząstek, które są pisane przez profesjonalne programy w c ++ (jak na przykład ROOT ). Jego główną zaletą jest to, że można go rozszerzać prawie bez końca, zachowując kompatybilność wsteczną.
źródło
struct
i kazałbym wywołującemu go utworzyć, wypełnić pola dla różnych opcji, a następnie przekazać je przez adres lub przekazaćNULL
domyślne opcje.Prawdopodobnie najlepszym sposobem na zrobienie tego (co może, ale nie musi być możliwe w twoim przypadku, w zależności od twojej sytuacji) jest przejście do C ++ i użycie go jako „lepszego C”. Możesz używać C ++ bez użycia klas, szablonów, przeciążania operatora lub innych zaawansowanych funkcji.
To da ci wariant C z przeciążeniem funkcji i parametrami domyślnymi (i wszystkimi innymi funkcjami, które wybierzesz). Musisz być trochę zdyscyplinowany, jeśli naprawdę poważnie podchodzisz do używania tylko ograniczonego podzbioru C ++.
Wiele osób powie, że używanie C ++ w ten sposób jest okropnym pomysłem i mogą mieć rację. Ale to tylko opinia; Myślę, że warto korzystać z funkcji C ++, z którymi czujesz się komfortowo, bez konieczności kupowania całości. Myślę, że istotną przyczyną sukcesu C ++ jest to, że okropnie wielu programistów wykorzystało go we wczesnych dniach właśnie w ten sposób.
źródło
Jeszcze inna opcja wykorzystuje
struct
s:źródło
Nie.
źródło
20202020
w kodzie szesnastkowym, ale jak go wpisać?Kolejna sztuczka z użyciem makr:
Jeśli przekazany zostanie tylko jeden argument,
b
otrzymuje wartość domyślną (w tym przypadku 15)źródło
Nie, ale możesz rozważyć użycie zestawu funkcji (lub makr) w celu przybliżenia przy użyciu domyślnych argumentów:
źródło
Tak, dzięki funkcjom C99 możesz to zrobić. Działa to bez definiowania nowych struktur danych lub mniej i bez konieczności decydowania przez funkcję w czasie wykonywania, jak zostanie ona wywołana, i bez narzutu obliczeniowego.
Szczegółowe wyjaśnienie znajduje się w moim poście pod adresem
http://gustedt.wordpress.com/2010/06/03/default-arguments-for-c99/
Jens
źródło
Generalnie nie, ale w gcc Możesz ustawić ostatni parametr funcA () jako opcjonalny w makrze.
W funcB () używam specjalnej wartości (-1), aby zasygnalizować, że potrzebuję wartości domyślnej parametru „b”.
źródło
Poprawiłem Jens Gustedt za odpowiedź , tak aby:
variadic.h:
Uproszczony scenariusz użytkowania:
I z _Generic:
I z wyborem nazwy funkcji variadic, której nie można łączyć z _Generic:
źródło
TAK
Poprzez makra
3 parametry:
Jeśli chcesz czwartego argumentu, musisz dodać dodatkowy my_func3. Zwróć uwagę na zmiany w VAR_FUNC, my_func2 i my_func
4 parametry:
Jedynym wyjątkiem jest to, że zmienne zmiennoprzecinkowe nie mogą mieć wartości domyślnych ( chyba że jest to ostatni argument, jak w przypadku 3 parametrów ), ponieważ potrzebują kropki („.”), Co nie jest akceptowane w argumentach makr. Ale może wymyślić obejście, jak widać w makrze my_func2 ( przypadek 4 parametrów) )
Program
Wynik:
źródło
Tak, możesz zrobić coś simulair, tutaj musisz znać różne listy argumentów, które możesz uzyskać, ale masz tę samą funkcję do obsługi, to wszystko.
źródło
Dlaczego nie możemy tego zrobić?
Podaj opcjonalny argument wartość domyślną. W ten sposób obiekt wywołujący funkcję niekoniecznie musi przekazywać wartość argumentu. Argument przyjmuje wartość domyślną. I łatwo ten argument staje się opcjonalny dla klienta.
Na przykład
void foo (int a, int b = 0);
Tutaj b jest argumentem opcjonalnym.
źródło