PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C] Rückgabewerte einer Funktion


Ajax
2009-01-21, 21:18:30
Gibt es eine Möglichkeit in einem C-Programm einen float-Wert an eine C-Funktion zu übergeben und zwei Ergebnisse der Funktion zu bekommen, welche ich zurückgeben kann?

Also zur besseren Vorstellung. Radius übergeben und theoretisch Umfang oder Fläche zurückzubekommen.

Der Witz ist eben nicht zwei Funktionen zu haben, sondern lediglich eine.

Marscel
2009-01-21, 21:22:05
Den Kram in ein Array oder struct packen?

Gnafoo
2009-01-21, 22:07:22
Entweder ein Array oder Struct zurückgeben, oder einen der Parameter als Pointer (in C++ als Referenz) übergeben, so dass der Aufrufer eine Variable angeben kann, in welche das Ergebnis geschrieben werden soll.

Eine direkte Unterstützung für mehrere Rückgabewerte gibt es in C nicht.

Coda
2009-01-21, 22:09:29
Falls auch C++ möglich ist gäbe es noch std::pair.

Ajax
2009-01-21, 22:12:38
:uponder:

Leider nur C.

Ich probier es mal mit:
int kreis(float r, float *u, float *f)
{
*u = 2 * r * M_PI;
*f = r * r * M_PI;
return 1;
}

noid
2009-01-21, 22:17:37
:uponder:

Leider nur C.

Ich probier es mal mit:
int kreis(float r, float *u, float *f)
{
*u = 2 * r * M_PI;
*f = r * r * M_PI;
return 1;
}

Ja, und nur weil C c als Namen trägt sind variablen nicht auf ein Zeichen beschränkt. Nur so als Tipp ;)

Gast
2009-01-21, 22:59:01
Eine direkte Unterstützung für mehrere Rückgabewerte gibt es in C nicht.


Nur mal so aus Interesse: welche erwähnenswerten Sprachen (die im Leben auch ne Rolle spielen) tun das? Hab ich mich schonmal gefragt.

Coda
2009-01-21, 23:16:21
Python erlaubt sowas:

def test():
return 1, 2, 3

Was automatisch ein Tupel erzeugt als Rückgabewert.

Kann dann so verwendet werden:

a, b, c = test()

Auch funktionale Sprachen haben das öfters mal.

Gnafoo
2009-01-21, 23:30:06
C# unterstützt mehrere out-Parameter. Das ist so eine Art Mischung aus Rückgabewert und Parameter. z. B. um in einer Funktion auf einen Schlag zu dividieren und den Divisionsrest zu bestimmen:


int rem;
int div = Math.DivRem(100, 21, out rem);


Ist aber auf der anderen Seite auch nicht ganz das selbe wie eine Referenz:
http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx

Ectoplasma
2009-01-22, 15:29:47
So geht das. Der Name des Structs ist natürlich nicht schön, aber das Beispiel sollte reichen.


#include <stdio.h>

#ifndef M_PI
#define M_PI 3.141592653
#endif


typedef struct _RESULT {
double u;
double f;
} RESULT;



RESULT
circle(double r) {
RESULT result;

result.u = 2.0 * r * M_PI;
result.f = r * r * M_PI;
return result;
}


int main(int argc, char* argv[]) {
RESULT result;

result = circle(2.3);
printf("u = %lf, f = %lf\n", result.u, result.f);
return 0;
}

Gast
2009-01-26, 02:30:56
:uponder:

Leider nur C.

Ich probier es mal mit:
int kreis(float r, float *u, float *f)
{
*u = 2 * r * M_PI;
*f = r * r * M_PI;
return 1;
}

Eleganter sit es so:


main()
{
...
float array[1];
...
}

void kreis(float r, float *array)
{
*array[0] = 2 * r * M_PI;
*arrray[1] = r * r * M_PI;
}


Damit legst du 2 Werte in ein Array ab und kannst sie dann je nach Bedarf abfragen.

Falls du die Arrays inkrementieren willst, dann kannst du das Feld um 1 erweitern
und dieses als Nullbyte nutzen.

Coda
2009-01-26, 02:33:34
Ja ganz Klasse Herr Gast. Das nächste Mal bitte Code ohne zwei völlig offensichtliche Fehler.

Gast
2009-01-26, 02:34:16
So geht das. Der Name des Structs ist natürlich nicht schön, aber das Beispiel sollte reichen.


#include <stdio.h>

#ifndef M_PI
#define M_PI 3.141592653
#endif


typedef struct _RESULT {
double u;
double f;
} RESULT;



RESULT
circle(double r) {
RESULT result;

result.u = 2.0 * r * M_PI;
result.f = r * r * M_PI;
return result;
}


int main(int argc, char* argv[]) {
RESULT result;

result = circle(2.3);
printf("u = %lf, f = %lf\n", result.u, result.f);
return 0;
}



Viel zu Speicherintensiv und langsam.

Du kopierst die Werte ja doppelt bei der Übergabe.
Meine Variante ist schneller.


Ich liebe Zeigerarithmetik und Pointer! :rockt:

Gast
2009-01-26, 02:35:33
Ja ganz Klasse Herr Gast. Das nächste Mal bitte Code ohne zwei völlig offensichtliche Fehler.


Ich war zu schreibfaul um vor das main ein int zu schreiben.
Außerdem muß der Threadstarter ja selber noch Programmieren lernen, da kann er also ruhig ein paar Fehler haben.

Coda
2009-01-26, 03:33:00
Ich war zu schreibfaul um vor das main ein int zu schreiben.
Das meinte ich nicht.

Viel zu Speicherintensiv und langsam.

Du kopierst die Werte ja doppelt bei der Übergabe.
Meine Variante ist schneller.
Das optimiert jeder noch so grenzdebile Compiler weg.

Ich liebe Zeigerarithmetik und Pointer! :rockt:
Ja genau, deshalb machst du auch genau an dieser Stelle Anfängerfehler :rolleyes:

Oid
2009-01-26, 08:57:42
Vielleicht klärst du uns lieber über die zwei Fehler auf, anstatt den Gast dumm anzumachen, Herr Coda.

Marscel
2009-01-26, 09:55:50
Unter Vorbehalt, dass ich kein C-Vertreter bin, aber

float array[1];

wird ein Array, das exakt eine float-Komponente haben kann, nicht zwei. Für den Rest kenn ich mich nicht sicher genug mehr aus.

squall23
2009-01-26, 09:59:35
Eleganter sit es so:


main()
{
...
float array[1];
...
}



array hat die falsche Größe.

sollte float array[2];
sein

Eleganter sit es so:


void kreis(float r, float *array)
{
*array[0] = 2 * r * M_PI;
*arrray[1] = r * r * M_PI;
}



du dereferenzierst einmal zu viel.
also nur

array[0] = 2 * r * M_PI;
array[1] = r * r * M_PI;


HTH

Ectoplasma
2009-01-26, 10:15:54
Vielleicht klärst du uns lieber über die zwei Fehler auf, anstatt den Gast dumm anzumachen, Herr Coda.

Ich gebe Coda Recht. Und es sollte bei zwei Zeilen Code, nicht allzu schwer sein, den Fehler zu sehen.

*array[0] = 2 * r * M_PI;

Und davon mal ab, hat der Gast einen mieserablen Stil und offenbar nicht die geringste Ahnung, wie ein Compiler optimiert.

Gnafoo
2009-01-27, 12:54:59
Zudem ist es eigentlich generell Quatsch ist, solche "Optimierungen" einzubauen, wenn man die Funktion vielleicht dreimal in 10 Minuten aufruft. Erstmal sauberen Code schreiben, der sich gut warten lässt und dann im Zweifelsfall die Engstellen optimieren (wenn sich auf algorithmischer Ebene nichts verbessern lässt). Dieses vorauseilende Optimieren schafft mehr Probleme als es löst.

carcass
2009-01-27, 20:32:21
...

Abraxus
2009-01-27, 22:41:23
Also jetzt Stil hin oder her, ich hab mal versucht genau das zu schreiben was du dir vorgestellt hast. An die Funktion wird ein float Wert übergeben und dann ein Array mit den 2 Ergebnissen zurückgegeben. Die main ist natürlich nur zum testen.
Es ist schlicht und ergreifend Falsch. Es wird nirgendwo garantiert, dass das Array noch existiert.
Was ihr euch immer alle einen abbricht, ich würde zwei Referenzen übergeben und gut ist. Ne stuct zurückgeben ist evtl. auch nicht verkehrt.

carcass
2009-01-27, 23:29:59
Es ist schlicht und ergreifend Falsch.
Dein Satz ist schlicht und ergreifend falsch.
Wegen Leuten wie dir überlege ich mir immer 3x irgendwo zu posten. Es bringt doch hier überhaupt nichts so einen Kommentar abzugeben ohne weitere Details oder einer besseren Lösung.

Trap
2009-01-27, 23:38:38
Zeiger auf lokale Variablen einer Funktion zurückzugeben ist keine neue Idee und die Erklärung warum man es nicht machen sollte ist Bestandteil jeder guten C/C++ FAQ.

Ectoplasma
2009-01-28, 09:12:44
@carcass, dein Beispiel von oben gehört wirklich verboten. 10 Jahre Informatikerknast sollte es dafür geben. Das lokale Array ist schlicht und einfach invalide, nachdem du den Funktions-Scope verlässt. Wenn du zwischen durch noch eine andere Funktion aufrufst, bevor du das Ergebnis von "funk" auswertest, ist es sogar 100 prozentig zerstört.

Mond
2009-01-28, 09:37:51
Das lokale Array ist schlicht und einfach invalide, nachdem du den Funktions-Scope verlässt. Wenn du zwischen durch noch eine andere Funktion aufrufst, bevor du das Ergebnis von "funk" auswertest, ist es sogar 100 prozentig zerstört.

Ich bin neu im Feld der Programmierung und kenne mich in C nur wenig aus, verfolge diesen Thread aber schon laenger. Koenntest Du mir das was Du geschrieben hast ein wenig genauer erklaeren?

The_Invisible
2009-01-28, 09:41:10
deswegen lieben wir alle C/C++ ;)

schon deswegen kenne ich viele die C/C++ wegen diesem "feature" meiden, obwohl speicher reservieren und freigeben ja eigentlich nicht soviel aufwand ist...

mfg

noid
2009-01-28, 09:45:24
Ich bin neu im Feld der Programmierung und kenne mich in C nur wenig aus, verfolge diesen Thread aber schon laenger. Koenntest Du mir das was Du geschrieben hast ein wenig genauer erklaeren?

Der float-array wird zu beginn des Funktionsaufrufes allociert, nach beendigung ist er vllt noch da, oder auch nicht, da der scope nicht mehr da ist/sein muss.

Um einen Struct/Array erfolgreich zurückgeben zu können muss man eigentlich vor dem Aufruf Speicher allocieren und dann der Fkt übergeben (Zeiger). Damit kann man sicher sein, dass man an die Daten kommt. Alles andere ist höchst unsauber.
Genauso wie diese pseudo-optimieren mit dem array für 2 Werte. Große Seuche.

Mond
2009-01-28, 09:53:35
Der float-array wird zu beginn des Funktionsaufrufes allociert, nach beendigung ist er vllt noch da, oder auch nicht, da der scope nicht mehr da ist/sein muss.

Heisst also, dass es im Speicher ist und ggf. durch andere Ablegungen im Speicher zufaellig ueberschrieben werden koennte?

Pinoccio
2009-01-28, 09:54:30
Auch funktionale Sprachen haben das öfters mal.Skript-Sprachen ebenfalls, beispielsweise Matlab (http://www.mathworks.com/access/helpdesk/help/techdoc/index.html?/access/helpdesk/help/techdoc/ref/varargout.html&http://www.mathworks.com/access/helpdesk/help/techdoc/ref/nargin.html).deswegen lieben wir alle C/C++ ;)

schon deswegen kenne ich viele die C/C++ wegen diesem "feature" meiden+1

mfg

The_Invisible
2009-01-28, 09:59:44
Heisst also, dass es im Speicher ist und ggf. durch andere Ablegungen im Speicher zufaellig ueberschrieben werden koennte?

direkt nach funktionsaufruf könnte der rückgabewert sogar noch richtig sein, nach einem weiteren funktionsaufruf isses sicher weg bzw bekommst nur mehr bytemist.

mfg

Abraxus
2009-01-28, 10:22:25
main()
{
float z1, z2;
func(z1,z2);
}

void func(float &z1, float &z2)
{
z1 = foo;
z2 = bar;
}


das wird möglicherweise unter C nicht gehen alternativ schreibt man:


main()
{
float z1, z2;
func(&z1,&z2);
}

void func(float *z1, float *z2)
{
(*z1) = foo;
(*z2) = bar;
}


Das immernoch gern Speicher vom Stapel adressiert wird ist eine Unsitte, die nicht totzukriegen ist. Das ist sogar mehrfach in diesem Thread der Fall.

MikeB
2009-01-28, 10:56:26
Man muss nicht mal C-Profi sein um mit zu bekommen dass das ganz grosser Mist ist, man muss nur lesen können. Die Compiler meckern das nämlich an:

(Visual Studio) warning C4172: returning address of local variable or temporary
(gcc) warning 1070: returning pointer to local variable

Wer solche Warnings ignoriert, dem gehört direkt in den Fuss geschossen.

Michael

noid
2009-01-28, 10:58:57
Man muss nicht mal C-Profi sein um mit zu bekommen dass das ganz grosser Mist ist, man muss nur lesen können. Die Compiler meckern das nämlich an:

(Visual Studio) warning C4172: returning address of local variable or temporary
(gcc) warning 1070: returning pointer to local variable

Wer solche Warnings ignoriert, dem gehört direkt in den Fuss geschossen.

Michael

Warnings gleich Error zu setzen ist ein schönes Ziel ;(

Ectoplasma
2009-01-28, 11:12:57
Um es nochmal präziser zu fassen. Lokale Variablen werden auf einem Stack angelegt, indem der Stack-Pointer dekrementiert wird, um so Speicher auf dem Stack zu schaffen. Beim verlassen einer Funktion, wird der Stack-Pointer wieder inkrementiert. D.h., dass die Werte der lokalen Varibalen zwar noch auf dem Stack sind, aber spätestens beim Aufruf einer anderen Funktion überschrieben werden, da es gibt nur einen Stack gibt.

Übrigens beim Beispiel von oben mit der Struktur als Rückgabewert, macht der Compiler impliziet folgende Optimierung.



RESULT result;

circle(double r, &result) {
...
}


Damit ist das Beispiel genauso schnell wie mit Pointern oder Array, nur 1000 mal lesbarer.

MikeB
2009-01-28, 11:14:47
Man kann per pragma Warnings auf Error setzen.
Ausserdem sollte ein Source IMMER mit "0 Errors, 0 Warnings" compilieren.

carcass
2009-01-28, 13:33:53
@carcass, dein Beispiel von oben gehört wirklich verboten. 10 Jahre Informatikerknast sollte es dafür geben.

Gibt es irgendeinen Grund mich so anzugehen? Es ging doch nur darum 2 Werte aus einer Funktion zurückzugeben oder? Das es außerhalb der Funktion nicht weiter existiert bzw. man später nicht mehr darauf rumrutschen kann war doch auch nicht verlangt. Ich dachte halt es ging drum nur einen Wert an die Funktion zu übergeben. Ansonsten übergibt man halt das array doch an die Funktion, kopiert die Ergebnisse rein und gibt nichts zurück.

MikeB
2009-01-28, 13:52:15
Aber zuverlässig funktionierender Code ist schon verlangt. Steppe mal im Debugger durch dein Programm, dann funktioniert es nicht mehr.
Ein Interrupt oder Ähnliches (Taskscheduling) würde dir bereits die Daten löschen.

patermatrix
2009-01-28, 13:58:26
Das es außerhalb der Funktion nicht weiter existiert bzw. man später nicht mehr darauf rumrutschen kann war doch auch nicht verlangt.
Wieso sollte er sonst etwas zurückgeben? :ucrazy4:

Gast
2009-01-30, 18:14:43
Und davon mal ab, hat der Gast einen mieserablen Stil und offenbar nicht die geringste Ahnung, wie ein Compiler optimiert.

Was soll bitteschön an dem Stil schlecht sein?
Wie sieht guter Stil aus?

Gast
2009-01-30, 18:17:12
Zudem ist es eigentlich generell Quatsch ist, solche "Optimierungen" einzubauen, wenn man die Funktion vielleicht dreimal in 10 Minuten aufruft.


Kleinvieh macht auch Mist.


Wenn du viele sehr viele Funktionen so langsam schreibst, dann summiert sich das zusammen.

Es hat seinen Grund, warum man alte Betriebssysteme mitsamt Desktop auf modernen Rechner innerhalb von 3 Sekunden booten kann, während heutige OS+Desktop Boliden wie z.b. Windows XP, Vista, Mac OS X oder Linux+Gnome oder KDE über 30 Sekunden bis Minuten brauchen, bis man endlich mit dem Rechner arbeiten kann.

Coder der Unfehlbarkeit
2009-01-30, 18:30:32
So ist es richtig und so sollte man es machen:


int main()
{
...
float array[2];
...
}

void kreis(float r, float *array)
{
array[0] = 2 * r * M_PI;
array[1] = r * r * M_PI;
}


Ein Struct muß erst generiert werden, ist langsam und bei gleichen Datentypen überflüssig.
Wenn ich eh 2 floatwerte habe, dann speichert man die in ein Array und nicht in ein Struct.
Außerdem spart man sich die Rückgabe des Structs.

Grüße,
Coder der Unfehlbarkeit

noid
2009-01-30, 21:33:09
Kleinvieh macht auch Mist.


Wenn du viele sehr viele Funktionen so langsam schreibst, dann summiert sich das zusammen.

Es hat seinen Grund, warum man alte Betriebssysteme mitsamt Desktop auf modernen Rechner innerhalb von 3 Sekunden booten kann, während heutige OS+Desktop Boliden wie z.b. Windows XP, Vista, Mac OS X oder Linux+Gnome oder KDE über 30 Sekunden bis Minuten brauchen, bis man endlich mit dem Rechner arbeiten kann.

Ein Trabbi ist auch schneller gebaut als eine E-Klasse. So What?
Du hast nichts verstanden. Man kann Code schnll und lesbar schreiben, nicht nur irgendwas ;)

Gnafoo
2009-01-30, 21:53:05
Kleinvieh macht auch Mist.


Wenn du viele sehr viele Funktionen so langsam schreibst, dann summiert sich das zusammen.

Es hat seinen Grund, warum man alte Betriebssysteme mitsamt Desktop auf modernen Rechner innerhalb von 3 Sekunden booten kann, während heutige OS+Desktop Boliden wie z.b. Windows XP, Vista, Mac OS X oder Linux+Gnome oder KDE über 30 Sekunden bis Minuten brauchen, bis man endlich mit dem Rechner arbeiten kann.

Natürlich macht Kleinvieh auch Mist. Allerdings nur dann, wenn es sich um Funktionen handelt die wirklich ständig und wiederholt vom Programm aufgerufen werden. Die restlichen Funktionen zu optimieren ist häufig einfach nur Quatsch. Schau dir einmal ein Programm im Profiler an. Das sind meist nur einige wenige Hotspots deren Optimierung sich überhaupt lohnt, weil der restliche Programmcode einfach gesagt nur eine Handvoll Male überhaupt durchlaufen wird. Davon abgesehen ist Feinoptimierung sowieso erst dann wirklich interessant, wenn die algorithmischen Möglichkeiten ausgeschöpft sind, denn da steckt meist viel mehr Potential drin.

Du musst ja auch berücksichtigen, dass heutige Softwaresysteme häufig sehr komplex sind. Feinoptimierung macht Programme häufig (natürlich nicht immer) schlechter wartbar und das kann sich später rächen. Daher ist es sinnvoller nur dort zu optimieren, wo die Optimierung auch einen nennenswerten Effekt zeigt.

Die Startzeit der Betriebsysteme hängt übrigens eher mit der Anzahl/Komplexität der Systemdienste, Treiber, Startprogramme etc. zusammen, als mit der Optimierung des dahintersteckenden Programmcodes (davon abgesehen ist der Bootvorgang wohl sowieso eher IO- als CPU-Limitiert). Heutige Betriebssysteme sind einfach komplexer, als es früher der Fall war. Du kannst mit Feinoptimierung nicht die Startzeit eines Windows XP oder Vista auf die Startzeit von Windows 3.11 drücken.

Ectoplasma
2009-01-30, 22:34:21
Oh man es gibt Leute die begreifen echt gar nichts. Der Compiler optimiert den struct so, dass der code der hinterher rauskommt exakt genauso schnell ist, wie bei der Lösung mit dem Array. Cool auch, dass diese Leute mit ihrem Unwissen ein Auftreten haben, dass einem echt Angst und Bange wird.

robobimbo
2009-01-30, 22:46:26
Tjo, und Grundregel ist sowieso:

Zuerst mal "schönen" und "wartbaren" Code scrheiben.

Die Optimierung findet erst dann statt, wenn es wirklich nötig ist. Performanceoptimierter Code ist der Regel schlechter wartbar und nicht so gut wiederverwertbar. Weiterhin verbringt man dann in der Entwicklung nicht unnötig viel Entwicklungsaufwand an den Stellen die ohnehin keiner Optimierung bedurften.

Coder der Unfehlbarkeit
2009-01-31, 00:40:42
Die Startzeit der Betriebsysteme hängt übrigens eher mit der Anzahl/Komplexität der Systemdienste, Treiber, Startprogramme etc. zusammen, als mit der Optimierung des dahintersteckenden Programmcodes (davon abgesehen ist der Bootvorgang wohl sowieso eher IO- als CPU-Limitiert). Heutige Betriebssysteme sind einfach komplexer, als es früher der Fall war. Du kannst mit Feinoptimierung nicht die Startzeit eines Windows XP oder Vista auf die Startzeit von Windows 3.11 drücken.

Das ist Unsinn.

Denn es gibt bereits ein hoch optimiertes OS, daß ebenso Server, Treiber Systemdienste und Co bietet wie dein Windows XP, aber deutlich schneller bootet.

Denn es ist durch und durch optimiert.
Es ist sogar komplett in Assembler programmiert und gerademal trotz seiner Funktionalität wenige MByte groß.

Hier schau selbst:
http://www.menuetos.net/



Cool auch, dass diese Leute mit ihrem Unwissen ein Auftreten haben, dass einem echt Angst und Bange wird.


Tja, ich muß euch schließlich sagen wer ich bin, damit ihr auch mein Wissen und meine Erfahrung zur Kenntnis nehmt.


Grüße,
Coder der Unfehlbarkeit

Gnafoo
2009-01-31, 01:14:53
Das ist Unsinn.

Denn es gibt bereits ein hoch optimiertes OS, daß ebenso Server, Treiber Systemdienste und Co bietet wie dein Windows XP, aber deutlich schneller bootet.

Denn es ist durch und durch optimiert.
Es ist sogar komplett in Assembler programmiert und gerademal trotz seiner Funktionalität wenige MByte groß.

;D

Das mag ja sein, aber da wurde eben mehr getan als nur Feinoptimierung, um das zu erreichen. Ich bestreite ja gar nicht, dass es möglich ist, ein Betriebssystem mit kurzer Startzeit zu bauen, sondern habe lediglich klargestellt, dass hinter der langen Startzeit aktueller Betriebssysteme (im Vergleich zu Früher) mehr steckt als "die aufsummierte zusätzliche Laufzeit, die man durch den Verzicht auf Optimierung in Kauf nimmt". Die spielt nämlich eher eine untergeordnete Rolle.

Außerdem ist das ein Vergleich von Äpfeln mit Birnen. Nimm die selbe Codebasis und zeige mir, dass Feinoptimierung bei der Startzeit Wunder bewirkt, dann glaube ich dir. Aber du hast keine Ahnung, was MenuetOS und Windows XP beim Start im Vergleich tun. Da läuft ganz anderer Code dahinter, also ist es auch nicht direkt vergleichbar und fällt eher in die Kategorie algorithmische Optimierung (wobei ich ein anderes Programm, was auf den ersten Blick das selbe tut ungerne als "algorithmische Optimierung" bezeichne :D). Und dass diese viel bewirken kann habe ich nie bestritten.

Edit: Arbeiten will ich mit dem Quellcode von MenuetOS zumindest nicht. Wartbarkeit ist etwas anderes (und ein paar Kommentare könnten dem Quellcode durchaus helfen). Dass das bisschen Quellcode im Vergleich zu Windows XP lächerlich ist muss ich nicht erwähnen, oder?

Pinoccio
2009-01-31, 11:46:47
(wobei ich ein anderes Programm, was auf den ersten Blick das selbe tut ungerne als "algorithmische Optimierung" bezeichne :D).Imho ist es doch ganeu das, das selbe Ergebnis bei weniger Aufwand durch bessere Algorithmen.

mfg

Oid
2009-01-31, 15:25:15
Hier vielleicht mal ein Vorschlag mit struct, falls es im ganzen geflame untergegangen ist ^^:



struct sKreis{
double Flaeche;
double Umfang;
};

void vCalcKreis(double Radius, struct sKreis *Kreis){
Kreis->Flaeche = PI*Radius*Radius;
Kreis->Umfang = PI*Radius*2;
}



Der Aufruf könnte dann so aussehen:



void main(){
double r=2;
struct sKreis MeinKreis;

vCalcKreis(r,&MeinKreis);
}



Danach stehen in MeinKreis die Werte drin.

Finde bei sowas ne struct schöner, weil man am Namen der Komponente auf den Inhalt schließen kann. Das ist bei nem Array nicht so, da hat man nur eine Index-Nummer.

Marscel
2009-01-31, 18:11:06
Aber jetzt hab ich mal als C-Noob eine Frage:

Einmal die Version von Oid, wo man die Speicheradresse von nem Struct übergibt, das schon vor der Berechnungsfunktion existiert, das dann beschrieben wird.

Ich (als Basic und PHP-Einsteiger) hätte nun die Funktion aufgerufen, in der dann ein Struct sKreis erstellt wird, das dann beschrieben und dann zurückgegeben wird (also eig. kopiert?).

Sind das zwei Wege zum selben Ziel oder ist an der einen Methode grundsätzlich etwas besser oder schlechter?

MikeB
2009-01-31, 18:21:18
... (also eig. kopiert?) ...
Dieses Kopieren optimiert der Compiler raus.

Also:

sKreis MeinKreis = vCalcKreis(r);

Der Compiler legt die Struktur auf dem Stack an und übergibt die Adresse an vCalcKreis(), dort wird dann direkt die neu angelegte Struktur beschrieben.

In der Praxis allerdings wird der Compiler eine so kleine Funktion automatisch "inlinen" und die Struktur auflösen.

Marscel
2009-01-31, 20:53:36
Soll heißen, hier ist das eigentlich egal, wie herum man es angeht.

Coder der Unfehlbarkeit
2009-01-31, 23:59:20
Nein, ein Return bei Reference ist immer schneller als ein Return bei Value, weswegen man es vermeiden sollte, Daten in die Funktion zu kopieren um sie dann wieder am Schluß zurückzukopieren.


Um ob der Compiler das rausoptimiert ist gar nicht so sicher,
denn es könnte ja sein, daß man das Struct der Main Funktion in einem anderen Thread für andere Daten benötigt.

MikeB
2009-02-01, 11:50:46
"Named Return Value Optimization" ist in VS seit 2005 und in gcc seit 3.1 implementiert.

Und das mit dem Thread ist ein bischen Blödsinn, oder werden jetzt Structs/Classes multithreaded auf dem Stack eines Threads angelegt?

Bietchiebatchie
2009-02-01, 14:40:43
Nein, das ist wenn man wirklich total super viel optimieren will, dann hält man Daten nur im Stack von einem Thread und greift dann von anderen Threads über die Adresse darauf zu. Weil dann hat man sich das Kopieren der Daten (viel zu teuer insbesondere, wenn es mehr als ein Byte ist) oder den Aufruf von malloc (am besten nie benutzen, weil auch viel zu teuer) für die Reservierung des entsprechenden Speicherplatzes gespart.

Oder so.