C Speicher in C Allozieren

Sahit

Admiral
Registriert
März 2010
Beiträge
7.373
Servus leute,
hätte folgende Frage bezüglich der C Programmierung.

Ich soll mittels der funktion malloc Arbeitsspeicher für Elemente reservieren und in einer Adressvariablen speichern.

Das ganze sollte folgendermaßen aussehen:

Code:
#define N 6
double x[N] = {17.2, -2, 34.4, 1.35, -2.7, 14.8}, *xpos;
.
.
.
xpos = (double *) malloc (sizeof(double)*npos;

npos ist die anzahl aller Positiven werte eines Feldes.

Nun meine frage:

Was genau sagt
Code:
xpos = (double *)
aus ?

alles was danach folgt ist mir klar also malloc....


* steht ja für pointer, aber so richtig klar komm ich mit pointern noch nicht :mad: und kann so auch nichts damit anfangen. Eine kurze Erläuterung von euch wäre cool :D

Sahit
 
(double *) ist ein typecast. Der sorgt dafür, dass xpos einen pointer durch malloc zugewiesen bekommt (oder genauer, dass der Pointer von Malloc, der zurückgegeben wird, als double-pointer interprtiert wird )und zwar auf den Anfang des eindimensionalen Feldes bzw. dessen Speicherbereiches.

Schau dir mal malloc unter cplusplus.com an, da findest du die ganze syntax.

LG

Oder anders formuliert: der Rückgabewert von Malloc wird durch (double*) als Pointer vom Typ double interpretiert, und dann in einem solchen, nämlich xpos, gespeichert.

PS: Ein Pointer speichert eine Adresse.
 
Zuletzt bearbeitet:
Ah ok danke für die schnelle Antwort super!
 
Gern, ich hoffe, ich habe das richtig formuliert, aber ich denke, du verstehst das Wesentliche^^
 
Konkret ist der Ausdruck äquivalent zu:

Code:
void* tmp = malloc(sizeof(double) * npos;
xpos = (double*) tmp;

d.h. rechts steht ein void-Pointer, und das vorangestellte (double*) sagt jetzt, dass dieser Pointer als Pointer auf doubles interpretiert werden soll, wie Modin666 schon schrieb.
 
Das ist eine C-Frage. Bitte nicht cplusplus.com als Referenz empfehlen. Die einfachste Möglichkeit zum Nachschlagen von libc-Funktionen sind immer noch manpages.

In C muss das Ergebnis von malloc nicht gecastet werden. Es wird sogar von einem nicht kleinen Teil der Community als schlechter Stil gewertet.
Viel wichtiger ist, das Ergebnis auf den Fehlerfall zu testen:
Code:
if (!(xpos = malloc (sizeof(double) * npos))) {
    // Fehlerfall retten. Wenn nicht möglich, Programmausführung sinnvoll beenden.
}
 
nullPtr schrieb:
In C muss das Ergebnis von malloc nicht gecastet werden. Es wird sogar von einem nicht kleinen Teil der Community als schlechter Stil gewertet.

Darüber kann man streiten...

nullPtr schrieb:
Viel wichtiger ist, das Ergebnis auf den Fehlerfall zu testen:

100% Zustimmung!

nullPtr schrieb:
Code:
if (!(xpos = malloc (sizeof(double) * npos))) {
    // Fehlerfall retten. Wenn nicht möglich, Programmausführung sinnvoll beenden.
}
Bei so einem Code rollen sich bei mir 2x die Fussnägel hoch!

Erstens:
Regel: In einer "if"-Anweisung NIEMALS eine Zuweisung machen!

Und zweitens:
Mit dem "!" verschleierst Du schön, daß Du eigentlich auf "NULL" testen willst.

Daher sollte der Code so aussehen:
Code:
xpos = malloc (sizeof(double) * npos);
if (xpos==NULL)
{
    // Fehlerfall retten. Wenn nicht möglich, Programmausführung sinnvoll beenden.
}

Der Compiler macht aus Deinem oder meinem Code höchstwahrscheinlich denselben Maschinencode, Du gewinnst also weder an Geschwindigkeit noch sparst Du Speicherplatz.


HTH

BigNum
 
Zuletzt bearbeitet: (Kosmetik)
BigNum schrieb:
Darüber kann man streiten...

Nee, kann man nicht. Es ist definitiv schlechter Stil. Zum einen erfolgt der cast implizit und ist somit nicht notwendig, und zum zweiten:

http://stackoverflow.com/questions/...-dangerous-about-casting-the-result-of-malloc
Ergänzung ()

BigNum schrieb:
Und zweitens:
Mit dem "!" verschleierst Du schön, daß Du eigentlich auf "NULL" testen willst.

Aber darüber kann man streiten. An ! gibt es meiner Meinung nach absolut nichts auszusetzen. Es ist funktional 100% äquivalent und außerdem kürzer.
 
antred schrieb:
Nee, kann man nicht. Es ist definitiv schlechter Stil. Zum einen erfolgt der cast implizit und ist somit nicht notwendig, und zum zweiten:

http://stackoverflow.com/questions/...-dangerous-about-casting-the-result-of-malloc
Über alles kann man streiten, dafür ist ein Forum doch da.

Das Argument "erfolgt implizit und ist somit nicht notwendig" ist zum Einen kein Argument. Mag sein, dass es nicht notwendig ist, das bedeutet aber nicht, dass es schädlich ist. Schlimmstenfalls dient der explizite Cast dann dazu, dass der menschliche Leser besser sieht, was vor sich geht.

Zum Zweiten: Hast Du Dir deine eigene Quelle mal durchgelesen: Dort findet sich kein einziges plausibles Argument gegen den Cast (außer vielleicht das 64-Bit-Argument). Das Credo spricht dort sehr deutlich für den Cast, insbesondere deswegen, weil man solchen Code später auch leichter als C++ kompilieren kann.
 
BAGZZlash schrieb:
Das Argument "erfolgt implizit und ist somit nicht notwendig" ist zum Einen kein Argument. Mag sein, dass es nicht notwendig ist, das bedeutet aber nicht, dass es schädlich ist. Schlimmstenfalls dient der explizite Cast dann dazu, dass der menschliche Leser besser sieht, was vor sich geht.

Unnötiger boilerplate code ist für mich immer schädlich. Man sollte sich beim Programmieren so ausführlich wie nötig aber so knapp wie möglich fassen, und sich unnötig zu wiederholen (und nicht anderes ist dieser Cast) ist das Gegenteil davon (don't repeat yourself - DRY).

BAGZZlash schrieb:
Zum Zweiten: Hast Du Dir deine eigene Quelle mal durchgelesen: Dort findet sich kein einziges plausibles Argument gegen den Cast (außer vielleicht das 64-Bit-Argument).

Das ist für mich ein sehr stichhaltiges Argument. Ein potentieller Fehler, der ohne den Cast schon beim Kompilieren auffallen würde, könnte durch den Cast verdeckt und dann zur Laufzeit zu undefiniertem Verhalten führen. Ich verstehe nicht, was es da zu diskutieren gibt.
 
antred schrieb:
[...] ist für mich immer [...]
Danke, das wollte ich nur wissen.

antred schrieb:
Das ist für mich ein sehr stichhaltiges Argument. Ein potentieller Fehler, der ohne den Cast schon beim Kompilieren auffallen würde, könnte durch den Cast verdeckt und dann zur Laufzeit zu undefiniertem Verhalten führen. Ich verstehe nicht, was es da zu diskutieren gibt.
Ja, wenn dieser Code als C (nicht als C++) mit einem 64-Bit-Compiler kompiliert würde und dann zur Laufzeit der Pointer auf einen Speicherbereich jenseits der 4-GB-Grenze zeigen würde, würde das zu undefiniertem Verhalten führen.

Bis der Threadstarter das macht, hat er genug gelernt, um diesen Fehler zu vermeiden, oder er nutzt für 64-Bit-Code einen C++-Compiler. Bis dahin lernt es sich besser, wenn man sieht, was passiert. :mussweg:
 
BigNum schrieb:
Regel: In einer "if"-Anweisung NIEMALS eine Zuweisung machen!

Solange ich klar mache, dass eine Zuweisung gemeint ist (über das extra Klammernpaar) ist alles okay und man spart Code und dem Leser die Assoziation des Mallocs mit der anschließenden Bedingung. Ich halte meinen Code für einwandfrei.
 
nullPtr schrieb:
Solange ich klar mache, dass eine Zuweisung gemeint ist (über das extra Klammernpaar) ist alles okay

Das halte ich für einen Fall von übertriebener Kürze zulasten der Lesbarkeit.
Gerade heutezutage halte ich Code der leichter wartbar, also auch lesbar und explizit ist, für besser als einen möglichst kurzen - dieses Paradigma ist für mich einfach überholt, wenn's nicht gerade um Golfing geht.
 
Naja, dass die eine Version besser lesbar oder wartbar als die andere ist würde ich nicht als gegeben hinnehmen.
 
Also so eigentlich wird im jedem Buch wo es um sauberen Code geht gesagt das man keine Zuweisungen in if-Anweisungen machen sollte und das hat eben den Grund der besseren Lesbarkeit und damit auch Wartbarkeit!
Man hat dadurch einfach keine Vorteile! Der Compiler wird dir daraus genau das gleiche generieren. Man Spart also eine Zeile riskiert aber Probleme bei der Wartung.
 
@Fonce: Es behauptet doch (hoffentlich) auch niemand, das hätte irgendwelche Auswirkungen auf den generierten Code. Es geht mir rein um das Les-/Wartbarkeitsargument:

Ich bin eben der Meinung, dass es für die Les- und Wartbarkeit sogar besser sein kann kann den Funktionsaufruf und die Fehlerüberprüfung in einen Block zu packen.
Gerade C-API's signalisieren Erfolg oder Misserfolg meistens über den Rückgabewert, was dann zu folgenden Konstrukten führt:
Code:
if(!foo()) {
   //...handle error
}
if(bar() != SUCCESS){
  //...handle error
}
if(baz() == -1){
  //...handle error
}


Die Schreibweise von nullPtr scheint nur die logische Fortführung dieses Schemas.
Das Problem mit Lesbarkeit ist halt immer, dass sie stark davon abhängt, was mam gewohnt ist. Muster die man häufig sieht erkennt man leicht wieder.

Ich möchte damit nicht sagen, dass mir persönlich die eine oder andere Schreibweise besser gefällt - nur dass mir die Sache nicht so eindeutig darstellt wie euch. Sollte vielleicht noch erwähnen, dass ich fast nur C++ programmiere. Mein Wissen darüber, was sich im C-Umfeld bewährt hat und was nicht und warum ist entsprechend beschränkt - daher meine Frage.
 
Im falle von Funktionsaufrufen kann man das ja auch machen(aber auch hier gibt es Ausnahmen!), hier ging es aber um Zuweisung innerhalb der If-Anweisung.
In der Praxis findet man dann z.B. solch bescheuerten Code weil einige das für ne gute Idee hielten. :rolleyes:

Code:
INIFileKp foobar::LoadIni(const std::string& filename)
{
	INIFileKp theINI;
	char *value, *temp;
	std::string section;
	char buffer[1000];
	std::fstream file(filename, std::ios::in);
	while (file.good())
	{
		memset(buffer, 0, sizeof(buffer));
		file.getline(buffer, sizeof(buffer));
		if ((temp = strchr(buffer, '\n')))
		{
			*temp = '\0';
		}
		if ((temp = strchr(buffer, '\r')))
		{
			*temp = '\0';
		}
		if ((buffer[0] == '[') && (temp = strrchr(buffer, ']')))
		{
			*temp = '\0';
			section = &buffer[1];
			PutIniSetting(theINI, &buffer[1]);
		}
		else if (buffer[0] && (value = strchr(buffer, '=')))
		{
			*value++ = '\0';
			PutIniSetting(theINI, section.c_str(), buffer, value);
		else if (buffer[0])
		{
			PutIniSetting(theINI, section.c_str(), buffer, "");
		}
	}
	return theINI;
}
 
Zuletzt bearbeitet:
Also ich finde nicht, dass der Code lesbarer wird, wenn man die Zuweisungen rauszieht, aber gut - über geschmack lässt sich bekanntlich streiten.
 
Zurück
Oben