Frage zu free(*Zeiger)
-
CStoll schrieb:
JDHawk schrieb:
Stimmt das so?
Nein - offiziell vorgegeben sind nur Minimalgrößen für die Datentypen (afair short und int >= 2 Byte, long >= 4 Byte) und die Hierarchie char*<=short<=int<=long.
* bei char ist definiert, daß es immer 1 Byte groß ist - und daß dieses Byte mindestens 8 Bit hat.
Die Mindestgrößen ergeben sich indirekt über die (Mindest-)Zahlenbereiche, die in diesen Datentypen speicherbar sein müssen. Das sind daher Größen in Bits. Ein long hat mindestens 32 bit, denn der Zahlenbereich von -(232-1)...(232-1) [^ hier für Potenz] muss darin darstellbar sein. Über den Wert von siezof sagt das erst etwas aus, wenn man die Anzahl der Bits von char kennt - sollte ein char zufällig auch 32 bit haben, könnte sizeof(long) ohne Weiteres 1 sein.
-
supertux schrieb:
Nun ist es aber so, dass der Anfang des zweiten reservierten Speicherbereiches gleich neben den ersten liegt.
Unsinn. Es gibt keinerlei Garantien hinsichtlich der relativen Lage beider Speicherbereiche (abgesehen davon, dass letzterer hinreichend ausgerichtet für ein int sein muss, was deine Darstellung extrem unwahrscheinlich macht).
-
camper schrieb:
supertux schrieb:
Nun ist es aber so, dass der Anfang des zweiten reservierten Speicherbereiches gleich neben den ersten liegt.
Unsinn. Es gibt keinerlei Garantien hinsichtlich der relativen Lage beider Speicherbereiche (abgesehen davon, dass letzterer hinreichend ausgerichtet für ein int sein muss, was deine Darstellung extrem unwahrscheinlich macht).
deswegen habe ich meinen Beitrag editiert und darauf hingewiesen, dass dieses Szenario möglich ist. Aber es geht nicht darum, ob zwei mallocs diese Konstellation erzeugen, sondern dass wenn du so etwas hast, dann überschreibst du fremden Speicher.
Ich geb's zu, es ist sogar unwahrscheinlich, dass dieses Szenario so auftaucht, aber deswegen sollte man nicht schlamping sein und ein int *ptr = malloc(1); machen. Und darum geht es.
-
camper schrieb:
Über den Wert von siezof sagt das erst etwas aus, wenn man die Anzahl der Bits von char kennt - sollte ein char zufällig auch 32 bit haben, könnte sizeof(long) ohne Weiteres 1 sein.
Interessant zu wissen. Aber wann hat ein char 32bit?
CStoll sagt ein char ist immer fest 1Byte groß.Sorry bin Anfänger und muss das fragen.
-
Hallo,
mcr schrieb:
x = malloc(1);
Hier forderst du einen Speicherbereich von 1 Byte an. Jedoch macht es
nur Sinn ein vielfaches von 4 Byte zu allozieren.Das bedeutet so wie der Zeiger Deklariert wird, muß ich ihn in malloc angeben? | | V V wenn int *x; dann malloc(sizeof(int)); wenn unsigned char *x; dann malloc(sizeof(unsigned char));
Auch wenn ich mich jetzt in die Nesseln setz, ein Zeiger hat doch eine feste Größe, also ob er jetzt als int, char, double,... Deklariert wird ist gleich und könnte im Fall von C auch während des Programm Ablaufs auf unterschiedliche Datentypen Zeigen, wenn der Zugriff vom Programm gesteuert wird?
MFG matthi
-
JDHawk schrieb:
Interessant zu wissen. Aber wann hat ein char 32bit?
CStoll sagt ein char ist immer fest 1Byte groß.Ja, aber niemand schreibt vor, daß 1 Byte genau 8 Bit hat - laut Ansi-Standard sind das mindestens 8 Bit.
Edit:
c_newbie schrieb:
Auch wenn ich mich jetzt in die Nesseln setz, ein Zeiger hat doch eine feste Größe, also ob er jetzt als int, char, double,... Deklariert wird ist gleich und könnte im Fall von C auch während des Programm Ablaufs auf unterschiedliche Datentypen Zeigen, wenn der Zugriff vom Programm gesteuert wird?
Der Zeiger hat feste Größe, der Speicherbereich, auf den er verweist, normalerweise nicht. Und ein "T*" geht davon aus, mindestens sizeof(T) Platz zu haben, in den er Daten schreiben kann.
(übrigens ist es normalerweise unsinnig, Platz für einzelne Werte über malloc() anzufordern - da reicht es aus, eine Stack-Variable anzulegen)
-
CStoll schrieb:
JDHawk schrieb:
Interessant zu wissen. Aber wann hat ein char 32bit?
CStoll sagt ein char ist immer fest 1Byte groß.Ja, aber niemand schreibt vor, daß 1 Byte genau 8 Bit hat - laut Ansi-Standard sind das mindestens 8 Bit.
Hehe das ist ja cool. Habe mal gehört: "C hält sich an keine Standards, C hält sich nur an Kernighan & Richie". Jetzt weis ich warum.
Also ich gehe mal davon aus, dass sich alle seid den 60er Jahren zumindest darauf geeinigt haben das 1B=8b ist.
-
JDHawk schrieb:
Also ich gehe mal davon aus, dass sich alle seid den 60er Jahren zumindest darauf geeinigt haben das 1B=8b ist.
Die Zeit der 9-Bit-"Bytes" ist wohl vorbei, aber es gibt noch den einen oder anderen DSP mit 32-Bit-"Bytes".
-
CStoll schrieb:
c_newbie schrieb:
Auch wenn ich mich jetzt in die Nesseln setz, ein Zeiger hat doch eine feste Größe, also ob er jetzt als int, char, double,... Deklariert wird ist gleich und könnte im Fall von C auch während des Programm Ablaufs auf unterschiedliche Datentypen Zeigen, wenn der Zugriff vom Programm gesteuert wird?
Der Zeiger hat feste Größe, der Speicherbereich, auf den er verweist, normalerweise nicht. Und ein "T*" geht davon aus, mindestens sizeof(T) Platz zu haben, in den er Daten schreiben kann.
(übrigens ist es normalerweise unsinnig, Platz für einzelne Werte über malloc() anzufordern - da reicht es aus, eine Stack-Variable anzulegen)
Was ich eigentlich machen wollte ist eine Verkettete Liste, wobei es dem Listen Element gleich sein soll "was" im Zeiger *daten gespeichert wird denn dass weiß ich vorher nicht bzw. weiß ich nicht wie groß das sein wird.
typedef struct liste{ int *daten; struct liste *l_next; }
Wenn wir dass ganze nun umdrehen und in einem zu kleinen Zeiger einen zu großen Speicherbereich "ablegen" könnten doch keine Daten mehr überschrieben werden?
Funktioniert in so einem Fall free(*Z) noch?
MFG matthi
-
c_newbie schrieb:
typedef struct liste{ //<-- typedef, dann auch ... int *daten; struct liste *l_next; } // <-- name angeben!!!
Wenn wir dass ganze nun umdrehen und in einem zu kleinen Zeiger einen zu großen Speicherbereich "ablegen" könnten doch keine Daten mehr überschrieben werden?
Funktioniert in so einem Fall free(*Z) noch?
Jein, du kannst immer noch über den von dir allozierten Bereich zugreifen,
aber dafür musst der Programmierer sorgen, dass es nicht passieren kann.
In dem anderen Fall ist es einfach nur falsch, bzw. macht es einfach keinen
Sinn.Es gilt immer: Bei einem Zugriff auf eine Speicherstelle, musst du dir sicher
sein, dass du den Speicher angelegt hast und du auch drauf zugreifen darfst.Zu deiner zweiten Frage: Ja, das funktioniert, da malloc() sich die Größe
speichert!Vielleicht solltest du mal über folgenden Typen nachdenken:
struct liste{ void *daten; // <-- void* struct liste *l_next; }
Damit ist der Typ der Daten dem Benutzer überlassen. Und der Benutzer
muss sich darum kümmern, dass die Daten alloziert und wieder freigegeben
werden. Die Liste kümmert sich nur um die Aufbewahrung der Daten.Üblicherweise schreibt man Funktionen wie:
struct liste * add (struct liste *l, void *daten); void * get_first(struct liste *l, struct liste **cur); void * get_next(struct liste **cur);
Gruß mcr