C Generische Funktion (Template)

destiny

Lt. Junior Grade
Registriert
Okt. 2010
Beiträge
283
Vorweg, ich bin recht neu in C unterwegs, habe aber recht gute Kenntnisse in C#.

Ich sitze grade an einer Aufgabe, in der es darum geht aus Zahlenfeldern (int sowie double) verschiede Informationen wie Minimum, Maximum, Median...usw. auszulesen.

Nun habe ich das 'Problem', dass ich jede Funktion quasi 2 mal schreiben muss, 1x für int und 1x für double, obwohl sie genau das gleiche tun.
Aus C# kenne ich die Möglichkeiten der Generics, in C++ gibt es dafür wohl Templates, aber für C konnte ich nichts der Gleichen finden.

Bleibt mit somit nichts anderes übrig, als alle Funktionen 'doppelt' zu schreiben? Das scheint mir irgendwie kein guter Programmierstil zu sein...

Grüße, destiny
 
Ist wahrscheinlich nicht die Lösung die du suchst, aber könntest du nicht int-Arrays temporär in double-Arrays umwandeln?
 
C kennt keine Generizität im Stile von Generics/Templates. Die kanonische Umsetzung würde auf die Verwendung von "void*" hinauslaufen -> siehe zB qsort...

Das würde ich allerdings auch nicht machen, da würde ich eher darauf zurückgreifen, die ints in doubles umzuwandeln...
 
Tada, willkommen in C. Musst du doppelt schreiben, das ist die richtige Art. Allerdings hatte ich bisher fast immer einen C++ Compiler zur Verfügung und dann kannst du C schreiben, aber mit C++ kompilieren. C++ Templates werden auch teilweise von C Compilern unterstützt, z.B. früher beim CUDA C Compiler.
C hat noch eine Menge weiterer super Überraschungen auf Lager :P
 
Mich würde interessieren, was für eine Aufgabe das ist. Schule/Uni/Ausbildung/Arbeitgeber?

Ich würde einfach nicht C benutzen. "Moderne" Sprachen wie C++, C# usw. können halt das gleiche, haben aber besser Abstraktionsmechanismen, sind weniger fehleranfällig, wenn man sie richtig programmiert, usw. usf.
 
Sind Aufgaben von der Uni, d.h. Sprache kann ich leider nicht wählen.
Wenn ichs könnte, dann würde bei C# bleiben ;)

Die Idee mit der Umwandlung der ints in double hatte ich auch.
Allerdings ist das kein Guter Stil 2000 ints in double zu konvertieren, nur um sich das Funktionenschreiben zu sparen, oder?

PS: C stinkt :D
 
C-Programmierer würden wohl dazu raten das ganze 2 Mal zu Implementieren und dann zB via einem _Generic-Macro unter einem Namen zur Verfügung stellen...
 
das schreit geradezu nach c++ und templates...

die umwandlung von ints in doubles und zurück wird zwar wohl für deine zwecke funktionieren, ist aber natürlich etwas hässlich.

falls du 64-bit-ints benutzt, bedenke aber, dass die umwandlung int->double->int bei großen zahlen verlustbehaftet ist, da die auflösung von double irgendwann größer als 1 ist (2^53).
 
versuch 's mal mit union...

ich würde das mit unions managen. Der Vorteil ist der, das du Speicher

struct checkedUnion {
int type; // Variable zum Speichern des in der Union verwendeten Datentyps
union intFloat {
int i;
float f;
} intFloat1;
};

Die Variablen in der union Teilen sich den Speicherbereich. Das Snippet ist von http://de.wikibooks.org/wiki/C-Programmierung:_Komplexe_Datentypen geklaut. Da gibt 's auch Hintergrundwissen und Anwendungsbeispiele dazu.....
 
Also mal ehrlich: Bis auf den Doppelt-Schreiben Vorschalg führen alle "Tricks" zu unverständlichem und unwartbaren Code. Den Präprozessor sollte man meiner Meinung nach meiden, wo man nur kann. Und auch der Vorschlag mit dem Struct führt zu völlig sinnloser Komplexität ("Wozu warum sind da ints in meinem Float-Array?"), Speicherverbrauch ist hoch.
C ist halt nicht C#, aber man kann auch in C guten Code schreiben, auch wenn's schwieriger ist.

Im Übrigen lohnen sich gute C-Skills enorm. Weil C in vielen Anwendungen auch heute noch die einzige Sprache ist, die in Frage kommt, vor allem High-Performance Computing, Microcontroller.
 
was das makro von hancock macht weiß ich nicht,
hatte aber ein ähnliches problem zu lösen gehabt in php + js.

ich habe mir dort so geholfen das ich der funktion im 2. parameter mitgebe um welchen typ es sich handelt und nur an den punkten wo sich die verarbeitung unterscheidet wird per switch je nach typ eine andere operation ausgeführt.

bei dir würde es ja aber reichen einfach alles als double zu übergeben und anschließden wieder umzucasten.

2,3 oder 4 funktionen für eine und die selbe sache --> BÄH!
kann ich mich net mit anfreunden

das problem: wenn du einmal was ändern willst, musst du alle funktionen anpassen, das erhöht den wartungsaufwand ungemein.
 
misu schrieb:
Im Übrigen lohnen sich gute C-Skills enorm. Weil C in vielen Anwendungen auch heute noch die einzige Sprache ist, die in Frage kommt, vor allem High-Performance Computing, Microcontroller.
Sry, wenn ich dir da widersprechen muss, aber was sich lohnt ist Erfahrung im Schreiben von Lowlevel-Code. Man muss, denke ich, zwischen verschiedenen Blickrichtungen unterscheiden:

In vielen Fällen von Anwendungsprogrammierung helfen Abstraktionen dabei den Code wartbar, leserlich, sicher usw usf. zu machen. Was man dabei aber in heutiger Zeit trotzdem nicht vergessen darf, ist dass der Code auf einer Maschine läuft und man durch das Verständnis des Vorgänge in der Hardware den Code noch performanter gestalten kann.

Auf der anderen Seite gibt es Sprachen, die so sehr abstrahieren, dass man nicht mehr an die Hardware kommt.

C-Code ist nicht direkt schnell. Da gibt es den berühmten Vergleich zwischen qsort bei C und sort bei C++, wo C die Größe eines Elementes, die Zahl der Elemente des Containers und ein indirekter Funktionsaufruf auf die Sortierfunktion übergeben wird. In solchen Fällen ist C langsamer als C++.

Was man beim Programmieren von C lernen muss, ist ordentlich zu programmieren. Kein Garbage Collector, der hinter einem aufräumt, die Möglichkeit über malloc, free und Zeiger direkt an die Maschine zu gehen und ganz primitiven Hardwarecode zu schreiben etc. pp.
Wenn man unter solchen Umständen lernt, sicheren Code zu schreiben, hat man einen Vorteil.
Was ich aber hier als bessere Alternative sehe, ist C++. Ein Gedanke, der bei der Entwicklung von C++ von Anfang an bis heute eine Rolle spielt, ist: "Unter C++ darf es nur noch Platz für Assembler geben". Mit C++ kannst du, genau wie in C, mit einem Codewort rohen Assembler in den Code schreiben, du kannst mit malloc und free rohe Speicherbereiche holen und primitiven Kernelcode schreiben (auch wenn bestimmte Kernel-VIPs anders denken ;) ) usw. usf. Wenn du es aber nicht brauchst, hast du moderne Mechanismen, wie Templates, eine sicherere und bequemere Möglichkeit Objekte auf dem Heap zu erzeugen (new, delete) etc.
Da steht C++ C soweit ich weiß in absolut nichts nach. (Sofern du im C-Code keine Befehle wie new und delete benutzt, kannst du C-Code ja auch recht einfach durch nen C++-Compiler schicken.) Und wenn man Code als Template schreiben kann, dann kann der Code sogar schneller werden!

Was m.M.n. Sinn machen würde, wäre an der Uni nen ordentlichen Packen C++ unterrichten, wo man von Anfang an guten Stil lernt (auch kein Garbage Collector), und am Ende die Klappe aufmacht und direkt an die Hardware packt.

Sofern du dich mit High-Performance-Computing beschäftigst, solltest du dir vllt. mal diesen Artikel angucken: http://www.codeproject.com/Articles/340797/Number-crunching-Why-you-should-never-ever-EVER-us
Ich bin mir grade nicht ganz sicher, ob C dynamische Arrays hat. Sofern es sie dort nicht gibt, ist es ein Vorteil von C++, da dynamische Arrays wesentlich schneller sind als eine doppeltgelinkte Liste. Das hat auch was mit dem Verständnis der Funktionsweise von moderner Hardware zu tun. Wenn du in dem Feld tätig bist, glaube ich, dass es mal ein Blick wert wäre. ;)
Sofern du C# programmierst, ist es der gleiche Effekt, wie zwischen List (schnell) und LinkedList (langsam), da List in C# soweit ich weiß auch nichts anderes ist, als ein dynamisches Array.
In dem Fall waren die Väter von C# ganz clever, da List eher benutzt wird, als z.B. Vector (dynamisches Array in C++), da der Programmierer direkt skeptisch ist, wenn er vom primitiven Container "Liste" weggeht.

Sry, dass mein Post eher auf misu geantwortet hat, aber ich hoffe der TE kann auch etwas daraus ziehen. ;)
 
Zuletzt bearbeitet:
Wie wärs denn die evtl sehr komplizierten, langen statistischen Algorithmen nur 1x zu implementieren und dann zB über einen Typ-Parameter den Zugriff auf die Daten zu lösen? Also quasi eine zusätzliche "typabhängige Zugriffschicht" hinzuzufügen? So kann man die mathematik von den datentypen-nervereien trennen.
Is natürlich nich gerad Laufzeitoptimal aber auf jedne Fall wartbarer also copy&paste.

Ich hab gerad keinen richtigen PC mit compiler hier und daher hat das folgende wahrscheinlich 1000 syntax fehler aber ich hoffe die Idee wird verständlich

Code:
enum data_type
{
  int_type;
  double_type;
  // ... usw
}

// 1 wenn *ele1 < *ele2, 0 sonst
int is_smaller(void* ele1, void* ele2, data_type type)
{
  switch (type)
  {
    case int_type:
      return ( *((int*)ele1) < *((int*)ele2) );
    case double_type:
      return ( *((double*)ele1) < *((double*)ele2) );
    // ... usw
    default:
      return 0;
  }
}

int get_index_of_min_value(void* array, int array_size, data_type type)
{
  int result = 0; // index of min value
  for (int i = 0; i < array_size-1; ++i)
  {
    if (is_smaller(array[i], array[i+1], type))
      result = i;
  }
  return result;
}
 
Zuletzt bearbeitet:
Fortatus schrieb:
Sofern du dich mit High-Performance-Computing beschäftigst, solltest du dir vllt. mal diesen Artikel angucken: http://www.codeproject.com/Articles/340797/Number-crunching-Why-you-should-never-ever-EVER-us
Ich bin mir grade nicht ganz sicher, ob C dynamische Arrays hat. Sofern es sie dort nicht gibt, ist es ein Vorteil von C++, da dynamische Arrays wesentlich schneller sind als eine doppeltgelinkte Liste. Das hat auch was mit dem Verständnis der Funktionsweise von moderner Hardware zu tun. Wenn du in dem Feld tätig bist, glaube ich, dass es mal ein Blick wert wäre. ;)
klar kann man in C dynamische arrays implementieren (nämlich genau so, wie dynamische arrays in der STL implementiert sind - nur eben nicht als template).

es ist natürlich ein vorteil von C++, dass man sie nur einmal implementieren muss und das template dann für alle datentypen verwenden kann, während man in C dieses bequeme hilfsmittel nicht hat.

generell lässt sich jeder algorithmus in C mindestens genau so effizient implementieren wie in C++. will man aber den implementierungsaufwand klein halten (also zum beispiel nicht für jeden datentyp quicksort neu implementieren), ist natürlich C++ dann oft schneller.

bitte nicht falsch verstehen, ich selbst verwende C++ auch lieber als C (templates sind toll!), aber dein post las sich ein bisschen so, als ließen sich manche algorithmen in C nicht so effizient wie in C++ implementieren, was so nicht stimmt.
 
Zuletzt bearbeitet:
Sry, wollte nicht implizieren, dass es Sachen in C++ gibt, die man mit C nicht machen kann. C++ ist ja aus C gewachsen. Wenn man C++-Funktionalität in C nachbauen will geht das, man macht aber den Job vom Standardkomitee, STL-Entwicklern, Compilerentwicklern, die auf C++-exklusive Funktionen optimieren, usw usf. natürlich mit. :)
Und an dem Punkt würde ich mich fragen: Ich kann mit C alles machen, was ich mit C++ kann, kann mit C++ auch alles machen, was C kann. Und C++ gibt mir mehr Werkzeuge an die Hand, um schnell, sicher und bequem zu programmieren: Welche Sprache nehme ich? ^^

Natürlich kann man mit einer grundlegenden Sprache wie C alles programmieren, was sich ein Mensch ausdenken kann, weil sie aus den grundlegendsten Primitiven besteht.
 
@Fortatus: Ich stimme dir im Prinzip zu. Ich bin auch selbst kein besonders großer Fan von C. Aber in der Praxis muss man halt. Und teilweise auch in dummen Situation, z.b. Anwendungsprogrammen, die besser in Java o.ä. geschrieben wären. Anforderung kann durch Frameworks entstehen, durch Legacy Code, durch den Chef.

Meine Meinung ist eher: soviel Abstraktion wie möglich

Performance spielt einfach eher selten eine Rolle.

Jedenfalls sollte man, wenn man ein guter Programmierer sein will, auf allen Abstraktionleveln programmieren können. Außerdem hilft die low-level-knowledge beim guten high-level-Programmieren manchmal enorm.

Ich kenne reine Java-Programmierer, die sich der geringen Performance z.b. von Java Listen nicht bewusst sind, einfach weil sie keine Ahnung haben, wie so etwas realisiert ist.
 
Zurück
Oben