2016-04-21 6 views
-2

Ich versuche, eine Funktion zu schreiben, die Ordenierungen über ein beliebiges numerisches Array macht. Das Problem ist, dass C den Datentyp kennen muss, um das Array aufgrund seiner "Zeigernatur" ordnungsgemäß zu durchlaufen. Gibt es eine Möglichkeit, dass ich jedes Array übergeben kann, ohne den Typ zu kennen? Vielleicht mit dem void type?Übergeben Sie einen beliebigen Array-Typ an eine Funktion in C

void ordenation (void *array, ...) {} 
+1

Da Sie den Zeiger in Ihrer Funktion dereferenzieren müssen, warum nicht den richtigen Typ übergeben? Zeigen Sie Ihren Code und geben Sie weitere Informationen an. Entweder ist dies ein XY-Problem, oder Ihre Absicht ist nicht klar. – Olaf

+0

Was ist eine Ordenation? – EOF

+2

Und das ist nicht mit Zeigern verwandt, aber weil C statisch typisiert ist. Der Versuch, generischen Code in C zu schreiben, ist eine sehr schlechte Idee. Verwenden Sie eine dynamisch typisierte Sprache wie Python, wenn Sie möchten. – Olaf

Antwort

0

So verstehe ich Ihre Frage, bitte antworten Sie unten, wenn das nicht ist. Sie versuchen, eine Funktion in C zu erstellen, die Arrays mehrerer numerischer Typen (Float, Int usw.) akzeptieren kann.

Dies wird Funktionsüberlastung genannt. Dies ist in C11 über den Operator _Generic möglich. Siehe function overloading in C

Eine andere Option wäre, Funktionen mit einem anderen Namen zu erstellen, alle mit einer anderen Parameterliste. Also:

void ordenation_i(int *array); 
    void ordenation_f(float *array); 

Eine andere Möglichkeit wäre die Verwendung des void * -Typs. Das würde bedeuten, dass Sie einen beliebigen Zeiger darauf übergeben können und es möglicherweise nicht das ist, wonach Sie suchen. Sie müssen die Leere * auf einen Zeiger auf etwas anderes, wie einen Float, zurückwerfen. Wenn diese Operation fehlschlägt, haben Sie möglicherweise Probleme.

Das Problem in diesem Code ist jetzt, dass das Array nur als Float-Array verwendet werden kann.

Schließlich könnten Sie auch nur einen C++ - Compiler verwenden. Es sollte jeden C-Code kompilieren und Sie erhalten standardmäßig eine Funktionsüberladung.

void ordenation(int array[]){ 
     //do stuff 
    } 

    void ordenation(float array[]){ 
     //do stuff 
    } 
-1

können Sie die Funktion void ordenation (void *array) machen und Anordnungen von beliebigen Datentypen in die Funktion übergeben, solange Sie die Eingabe-Array geworfen wie diese ordenation ((void*)array) beim Aufruf der Funktion. Sie sollten wahrscheinlich eine zweite Eingabe hinzufügen, um den Datentyp des entsprechenden Arrays anzugeben, wenn Sie das Array in Ihrer Funktion verwenden möchten. (Ich nehme an, der Punkt davon ist, weil C nicht für Funktionsüberlastung erlaubt?)

+1

Willkürliche Zeiger auf 'int *' geworfen und erwartet werden, dass es funktioniert, ist nicht OK. Dafür ist 'void *' gedacht. –

+0

fair genug, ich habe meine Antwort bearbeitet. – Ben

0

können Sie absolut sicher einen Zeiger auf ein beliebiges Objekt an eine Funktion wie diese void * Verwendung übergeben. Das Problem besteht darin, dass Sie etwas mit diesem Objekt machen müssen, sobald Sie in dieser Funktion sind, und Sie müssen den Typ wissen, um dies zu tun, also auch, wenn Sie den Typ nicht benötigen Um einen Zeiger auf das Array zu übergeben, brauchen Sie es auf irgendeine Art und Weise, um die tatsächliche Arbeit erledigen zu können.

Sie können es mit C11-Generika tun, wie eine andere Antwort angibt, aber eine andere Möglichkeit besteht darin, nicht nur einen Zeiger auf das Array, sondern auch einen Zeiger auf den Code, der ausgeführt werden soll, mit einem Funktionszeiger zu übergeben.

Zum Beispiel wird der folgende Code zwei beliebigen numerischen Array zu jedem Element hinzufügen (ich habe es nur für int, implementiert long und double, aber es ist trivial für die übrigen Standard numerischen Typen zu implementieren). Die add_two() Funktion selbst hat nie eine Vorstellung davon, welche Art von Array es bekommt.Aber um dies zu erreichen, haben Sie es auch auf eine Funktion einen Zeiger übergeben, die tut wissen:

#include <stdio.h> 

void add_two(void * array, size_t sz, void (*add_func)(void *, size_t)); 
void add_two_int(void * array, size_t idx); 
void add_two_long(void * array, size_t idx); 
void add_two_double(void * array, size_t idx); 

int main(void) 
{ 
    int n[] = {1, 2, 3, 4, 5}; 
    add_two(n, 5, add_two_int); 
    for (size_t i = 0; i < 5; ++i) { 
     printf("%zu: %d\n", i, n[i]); 
    } 

    long l[] = {1L, 2L, 3L, 4L, 5L}; 
    add_two(l, 5, add_two_long); 
    for (size_t i = 0; i < 5; ++i) { 
     printf("%zu: %ld\n", i, l[i]); 
    } 

    double d[] = {1.0, 2.0, 3.0, 4.0, 5.0}; 
    add_two(d, 5, add_two_double); 
    for (size_t i = 0; i < 5; ++i) { 
     printf("%zu: %f\n", i, d[i]); 
    } 

    return 0; 
} 

void add_two(void * array, size_t sz, void (*add_func)(void *, size_t)) 
{ 
    for (size_t i = 0; i < sz; ++i) { 
     add_func(array, i); 
    } 
} 

void add_two_int(void * array, size_t idx) 
{ 
    int * n = array; 
    n[idx] += 2; 
} 

void add_two_long(void * array, size_t idx) 
{ 
    long * l = array; 
    l[idx] += 2; 
} 

void add_two_double(void * array, size_t idx) 
{ 
    double * d = array; 
    d[idx] += 2; 
} 

mit Ausgang:

[email protected]:~/src/sandbox$ ./genarray 
0: 3 
1: 4 
2: 5 
3: 6 
4: 7 
0: 3 
1: 4 
2: 5 
3: 6 
4: 7 
0: 3.000000 
1: 4.000000 
2: 5.000000 
3: 6.000000 
4: 7.000000 
[email protected]:~/src/sandbox$ 

Natürlich in diesem einfachen Beispiel gibt es nicht viel ist in die Art und Weise des echten Nutzen für das Schreiben der add_two() Funktion im Vergleich zu nur Schreiben add_two_int() und Freunde und die Verwendung von ihnen direkt. Aber in einem komplexeren Beispiel, in dem Sie zB add_two() in einer Bibliothek haben möchten, ist dies eine Möglichkeit für Sie, mit beliebigen und neuen Typen umgehen zu können, ohne add_two() ändern oder Ihre Bibliothek neu erstellen und implementieren zu müssen.

Auch ich habe die Funktion add_two() benannt, aber es führt offensichtlich nur, was Sie an jedem Element der Reihe nach liefern. So könnten Sie beispielsweise die Funktion subtract_two_int(void * array, size_t idx) schreiben, diese an add_two() übergeben, und sie wird tatsächlich zwei von jedem Element subtrahieren, trotz des Namens.

Verwandte Themen