2011-10-06 11 views
11

Soru şu ana kadar çok şey söylüyor.C: Değişken parametre sayımı olan işlevler için tek bir işlev işaretçisi dizisini nasıl kullanabilirim?

Bunun nasıl yapılacağından emin değilim ve işe yarayan hiçbir şeyin yakınında bir yere gelmeyin. İşte

bazı örnek fonksiyonları var:

add(int x, int y) { 
    return x+y; 
} 

ve Şimdiye kadar ikisi ile typedef kullanarak denedim

mean(int x1, int y1, int x2, int y2) { 
    return (x1 + y1 + x2 + y2)/4; 
} 

ama birine bir şey noktayı nasıl bilemiyorum her ikisi de: tür:

typedef int (*mathfunc2)(int x, int y); 
typedef int (*mathfunc4)(int x1, int y1, int x2, int y2); 

????? func_table[2] = {add, mean}; 

cevap

25

"Genel işlev işaretçisi" olarak kullanmak için bir işlev işaretçisi türü seçmeniz gerekir dizinizi tanımlamak için bu türü kullanın ve açık yayınları kullanın. Bir işlev işaretçi türünü diğerine dönüştürmek ve tekrar geri almak, değeri korumak için garanti edilir. Başka bir deyişle

:

typedef int (*generic_fp)(void); 

generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean }; 

O zaman doğru tip geri döküm gerekiyor add çağırmak için: Eğer daha lezzetli bulursanız bazı makrolar tanımlayabilirsiniz

result = ((mathfunc2)func_table[0])(x, y); 

:

#define FUNC_2(f, p1, p2) ((mathfunc2)(f))(p1, p2) 
#define FUNC_4(f, p1, p2, p3, p4) ((mathfunc4)(f))(p1, p2, p3, p4) 

result = FUNC_2(func_table[0], x, y); 
+0

Bu tam olarak hile yaptı! Teşekkürler bir demet efendim. Şimdiye kadar 15 itibarı elde edersem ve bir yukarı ok verirsem umarım hatırlayacağım :) – vaughanj

+0

Parametreler nedeniyle normal boşluk işaretleyicilerinden farklı şekilde davranan gösterim işlevi işaretleyicilerinin altındaydım. Yığın temizleme üzerinde bozuk olacağından, işlev işaretleyicilerini farklı parametrelerle karıştıramazsınız. Bir şeyi yanlış anlamış mıyım? – Ioan

+0

@Ioan: İşlev, bildirilen işlev türü ile uyumlu bir işaretçi aracılığıyla çağrılmalıdır; bu, işlev işaretçisini depolama için farklı bir türe dönüştürürseniz, çağrı yapmak için doğru türde döndürülmeniz gerektiği anlamına gelir. işlev. Bu cevaptaki örnek bunu yapar. – caf

0

Bu iki işlev türü uyumsuz. Kesin olarak, tamamen farklı argüman geçişi kullanılarak uygulanabilirler. Bir uygulama, örneğin, 3 parametreye kadar olan tüm fonksiyonların bunları yazmaçlardan almasını ve diğer tüm fonksiyonların bunları yığın üzerinden almasını seçebilir.

Yapabilecekleriniz, aynı parametre geçiş şemasını takip etmelerini sağlamak için her iki işlevi de varargs parametreleriyle tanımlamaktır.

Ne kadar parametre beklediklerini bilmeden, bu işlevleri nasıl çağırmayı planladınız?

3

Böyle Facade Pattern kullanabilirsiniz: Kod çirkin

int add(int x, int y); 
int mean(int x1, int y1, int x2, int y2); 

typedef int (*operation_fp)(int argc, int* argv); 

int add_wrapper(int argc, int* argv) { return add(argv[0], argv[1]); } 
int mean_wrapper(int argc, int* argv) { return mean(argv[0], argv[1], argv[2], argv[3]); } 

operation_fp func_table[2] = { add_wrapper, mean_wrapper }; 

rağmen, iş yapar. Sarmalayıcılarda bazı doğrulama mantığı eklemelisiniz.

1
int (*func[])() = { add, mean }; 
+0

Fonksiyon işaretçileri (int, int, int, int)' tipi 'int (*) (int pointer fonksiyonlarıyla * * uyumlu değildir, ...) '. – caf

+0

emin, Şuraya ekle() – BLUEPIXY