Wielokrotnie wpadam na problem z ustawianiem procedur obsługi sygnałów w kodzie GTK +, nie wymagającym kilku parametrów i mając pokusę użycia tej samej funkcji co obsługa dla kilku sygnałów, których programy obsługi mają różne sygnatury - ale z pierwszym N argumenty (te, na których mi zależy) to samo.Czy można bezpiecznie wywoływać funkcję C z większą liczbą argumentów, niż się spodziewa?
Czy jest bezpieczny (w tym sensie, że nie jest niezdefiniowanym zachowaniem, a nie bardziej pragmatycznym określeniem "działa na moim komputerze?"), Aby przekazywać wskaźniki do funkcji GObject API, gdy te funkcje wymagają mniejszej liczby argumenty, niż faktycznie otrzymają od procesu emisji sygnału?
Czy to rozwód z GTK +, czy ten kod jest w porządku?
/* Note: No void *userdata argument! */
void show(int x) {
printf("x = %d\n", x);
}
void do_stuff(void (*fn)(int, void *), void *userdata) {
static int total = 0;
(*fn)(total, userdata);
total++;
}
void doitnow(void) {
do_stuff(&show, NULL);
}
Aby uzyskać dodatkowe informacje, należy omówić implikacje różnych typów wartości zwracanych między podpisem funkcji a stroną połączenia.
Edit: An almost-identical question sondy „kompatybilny typ funkcji” dokładniej i zwraca an answer directly addressing my concrete problem - że z łańcuchowym gobject obsługi sygnałów. TL; DR: Tak, jest to niezdefiniowane zachowanie, ale jest praktycznie idiomatyczne (choć nie obowiązkowe) w niektórych zestawach narzędzi.
Jestem prawie pewien, że konwersja wskaźnika funkcji w ten sposób to UB. – Flexo
@Flexo Konwersja wskaźnika funkcji jest OK. Używając go do czegokolwiek innego niż do konwersji, z drugiej strony, ... –
BTW, nie ma potrzeby '(* fn)' w do_stuff. Po prostu wywołaj 'fn (total, userdata)'. Ponieważ 'fn' jest wskaźnikiem funkcji, operator wywołania funkcji' (total, userdata) 'robi dokładnie to, czego się spodziewałeś. – Jens