Speicher allozieren
-
Ich habe eine Funktion zum erstellen eines IntArray:
struct IntArray * createintarray(int length) { struct IntArray *a; a->length = length; a->field = malloc(a->length*sizeof(int)); return a; }
Leider kann ich es hier nicht so machen, weil ich ja einen Pointer auf ein IntArray zurückgeben muss.
struct IntArray * createintarray(int length) { struct IntArray a; ... }
Am liebsten würde ich es ja auch so machen:
struct IntArray * createintarray(int length) { struct IntArray a; a.length = length; a.field = malloc(a.length*sizeof(int)); return ?; }
Jedoch weiß ich dann nicht, was ich zurückgeben muss um einen Pointer auf a zu haben.
Ist halt eine Aufgabe an der Uni, da soll ich C benutzen.
-
Iberion schrieb:
Leider verstehe ich nicht was du hiermit nun meinst:
cooky451 schrieb:
Könntest du das nicht einfach auf dem Stack anlegen?
Außerdem hab ich gelesen, dass malloc normalerweise void zurückgibt und man deswegen den gewünschten Type casten soll, das machst du ja auch nicht, wieso?
Lokale Variablen (die in einer Funktion definiert werden) werden auf dem Stack (-> http://de.wikipedia.org/wiki/Stapelspeicher) angelegt.
Für die musst du den Specher nicht extra anfordern.In deinem Fall fällt das malloc für a weg.
-
@Iberion
Mit der Funktionssignatur musst du da in der Tat dynamisch Speicher reservieren. Macht aber keinen Sinn. Wenn du darfst, ändere einfach die Signatur zu:struct IntArray createintarray(int length) { struct IntArray a; a.length = length; a.field = malloc(a.length*sizeof(int)); return a; }
Wenn du das nicht darfst, frag mal deinen Prof was er sich dabei gedacht hat. Zudem sollte man eigentlich auch überprüfen ob malloc nicht 0 zurückgegeben hat, aber na ja bei so kleinen Uni Programmen kann man's auch lassen.
-
Dankeschön! Ich hab mich da halt sehr an die Folien des Übungsscript gehalten, nun verstehe ich zumindest einiges besser.
-
Sorry, wenn ich blöd frage, aber:
struct IntArray * createintarray (int length) { struct IntArray a; a.length = length; a.field = malloc(a.length*sizeof(int)); return &a; } int main (void) { struct IntArray *b; // b ist jetzt ein Pointer auf ein nicht initialisiertes IntArray ohne allokierten Speicherbereich b = createintarray (5); // Ich hätte gedacht, mit b kann ich hier jetzt nicht arbeiten // schließlich zeigt b auf einen Speicherbereich, der im Scope einer anderen Funktion liegt? // Würde man b als Argument an createintarray übergeben und die Funktion anpassen, sähe es natürlich anders aus ... }
-
Ja.
-
@Iberion: Deine Ausgangslösung war teilweise richtig.
@StupidQuestion: Wird irgendwann mal crashen.
Schon mal die Lösung mit GCC kompiliert? MS VStudio würde höchstwahrscheinlich auch meckern.
GCC warnung: "warning: function returns address of local variable"Bin der Meinung, dass die richtige Lösung so aussieht:
#include <stdlib.h> struct IntArray { int length; int *field; }; // 1.te Version struct IntArray* createIntArray (int length) { if(length < 0) { //auch <= sinnvoll return 0; //arrays mit negativen Groessen unzulaessig } struct IntArray* a = (struct IntArray*) malloc(sizeof(struct IntArray)); if(a != 0) { int* mem = (int*) malloc(length); if(mem == 0) { //Allokation fehlgeschlagen // bereits allozierten Speicher freigeben. free((void*)a); return 0; } //Groesse & Pointer zuweisen a->length = length; a->field = mem; return a; } //sonst Allokation fehlgeschlagen return 0; } // 2.te Version struct IntArray* createIntArray2 (int length) { if(length < 0) { //auch <= sinnvoll return 0; //arrays mit negativen Groessen unzulaessig } int* mem = (int*) malloc(length); if(mem == 0) { //Allokation fehlgeschlagen return 0; } struct IntArray* a = (struct IntArray*) malloc(sizeof(struct IntArray)); if(a != 0) { //Groesse & Pointer zuweisen a->length = length; a->field = mem; return a; } //Allokation fehlgeschlagen free( (void*) mem);// bereits allozierten Speicher freigeben. return 0; } int main (void) { struct IntArray *b; // b ist jetzt ein Pointer auf IRGENDWAS im Speicher // b kann, muss aber nicht, 0 sein b = createIntArray (5); if(b != 0) { // mit b weiterarbeiten ... } return 0; }
Spaßeshalber 2 Versionen. Kommentare erzählen alles.
Inkl. Null-Pointer-Überprüfungen.
Casts nach void* eigentlich nicht notwendig.
-
dimiKL schrieb:
@StupidQuestion: Wird irgendwann mal crashen.
Hast du seine Kommentare mal gelesen?
dimiKL schrieb:
Bin der Meinung, dass die richtige Lösung so aussieht:
Bitte cpp Tags nutzen.
Statt int lieber size_t, dann bleibt dir auch der Test erspart. (Aber gut, war ja so vorgegeben.)
Bei dir ist einmal der "Good-Path" und einmal der "Bad-Path" im if. Lieber einheitlich bleiben.
Rückgabetyp von malloc musste in C nicht casten.
Du alloziierst nur length statt length * sizeof(int) Byte!dimiKL schrieb:
Casts nach void* eigentlich nicht notwendig.
Warum machst du es dann?
-
Apropo Speicher alloziieren:
Wie macht ihr das bei zweidimensionalen Arrays? Macht ihr für jede Zeile ein malloc? Ich habe mir angewöhnt gleich den kompletten Speicher (Zeile * Spalte) zu alloziieren und dann mit Pointer-Arithmetik zu arbeiten. Das spart die vielen Aufrufe und Modi-Wechsel.
-
Steffo schrieb:
kompletten Speicher (Zeile * Spalte)
Ist ja auch richtig, wie du im C++ Forum gefühlt tausendfach nachlesen kannst.
-
Steffo schrieb:
Apropo Speicher alloziieren:
Wie macht ihr das bei zweidimensionalen Arrays? Macht ihr für jede Zeile ein malloc?Das wäre kein zweidimensionales Array mehr. Man muss schon wissen, was man möchte.
-
Was bringt dir ein zweidimensionales Array außer Komfort?
-
Steffo schrieb:
Was bringt dir ein zweidimensionales Array außer Komfort?
Steffo schrieb:
den kompletten Speicher (Zeile * Spalte)
-
@ccoky451: Hast recht lengthsizeif(int) müsste es heißen.
Casts? Einfach mal zur Vermeidung von Warnungen, bin sicher, dass es Compiler gibt, die nicht automatisch " int " auch als " void* " akzeptieren.
-
dimiKL schrieb:
Casts? Einfach mal zur Vermeidung von Warnungen, bin sicher, dass es Compiler gibt, die nicht automatisch " int* " auch als " void* " akzeptieren.
Ja, sogenannte C++-Compiler. Habe aber keine Ahnung, was dieses "C++" sein soll. Bestimmt ein Javadialekt.
Du verhinderst also bloß, dass du Fehler bemerkst.
-
SeppJ schrieb:
Habe aber keine Ahnung, was dieses "C++" sein soll. Bestimmt ein Javadialekt.
Das C steht in diesem Fall für Coffee.
-
SeppJ schrieb:
Ja, sogenannte C++-Compiler.
Da haste nicht ordentlich gelesen SeppJ.
Jeder C und jeder C++ Compiler akzeptiert eine implizite Konvertierung von int* zu void*. Jeder C, aber kein C++ Compiler akzeptiert die implizite Konvertierung von void* zu int*. Der Microsoft C Compiler warnt bei Letzterem, was nervig ist. Aber der Cast von int* zu void* ist einfach nur Quatsch.
-
malloc
in C++ !? Nötig?
-
Alles kann, nichts muss.
-
Swordfish schrieb:
malloc
in C++ !? Nötig?Klar, und dann gleich nen Placement new hinterher, macht das nicht jeder so?