No, you're not allocating memory for y->x twice.
Instead, you're allocating memory for the structure (which includes a pointer) plus something for that pointer to point to.
Think of it this way:
1 2
+-----+ +------+
y------>| x------>| *x |
| n | +------+
+-----+
You actually need the two allocations (1 and 2) to store everything you need.
Additionally, your type should be struct Vector *y since it's a pointer, and you should never cast the return value from malloc in C.
It can hide certain problems you don't want hidden, and C is perfectly capable of implicitly converting the void* return value to any other pointer.
And, of course, you probably want to encapsulate the creation of these vectors to make management of them easier, such as with having the following in a header file vector.h:
#include <stddef.h>
struct Vector {
double *data; // Use readable names rather than x/n.
size_t size;
};
struct Vector *newVector(size_t sz);
void delVector(struct Vector *vector);
//void setVectorItem(struct Vector *vector, size_t idx, double val);
//double getVectorItem(struct Vector *vector, size_t idx);
Then, in vector.c, you have the actual functions for managing the vectors:
#include <stdlib.h>
#include "vector.h"
// Atomically allocate a two-layer object. Either both layers
// are allocated or neither is, simplifying memory checking.
struct Vector *newVector(size_t sz) {
// First, the vector layer.
struct Vector *vector = malloc(sizeof (struct Vector));
if (vector == NULL)
return NULL;
// Then data layer, freeing vector layer if fail.
vector->data = malloc(sz * sizeof (double));
if (vector->data == NULL) {
free(vector);
return NULL;
}
// Here, both layers worked. Set size and return.
vector->size = sz;
return vector;
}
void delVector(struct Vector *vector) {
// Can safely assume vector is NULL or fully built.
if (vector != NULL) {
free(vector->data);
free(vector);
}
}
By encapsulating the vector management like that, you ensure that vectors are either fully built or not built at all - there's no chance of them being half-built.
It also allows you to totally change the underlying data structures in future without affecting clients. For example:
- if you wanted to make them sparse arrays to trade off space for speed.
- if you wanted the data saved to persistent storage whenever changed.
- if you wished to ensure all vector elements were initialised to zero.
- if you wanted to separate the vector size from the vector capacity for efficiency(1).
You could also add more functionality such as safely setting or getting vector values (see commented code in the header), as the need arises.
For example, you could (as one option) silently ignore setting values outside the valid range and return zero if getting those values. Or you could raise an error of some description, or attempt to automatically expand the vector under the covers(1).
In terms of using the vectors, a simple example is something like the following (very basic) main.c
#include "vector.h"
int main(void) {
struct Vector *myvec = newVector(42);
myvec->data[0] = 2.718281828459;
delVector(myvec);
}
(1) That potential for an expandable vector bears further explanation.
Many vector implementations separate capacity from size. The former is how many elements you can use before a re-allocation is needed, the latter is the actual vector size (always <= the capacity).
When expanding, you want to generally expand in such a way that you're not doing it a lot, since it can be an expensive operation. For example, you could add 5% more than was strictly necessary so that, in a loop continuously adding one element, it doesn't have to re-allocate for every single item.
Answer from paxdiablo on Stack OverflowNo, you're not allocating memory for y->x twice.
Instead, you're allocating memory for the structure (which includes a pointer) plus something for that pointer to point to.
Think of it this way:
1 2
+-----+ +------+
y------>| x------>| *x |
| n | +------+
+-----+
You actually need the two allocations (1 and 2) to store everything you need.
Additionally, your type should be struct Vector *y since it's a pointer, and you should never cast the return value from malloc in C.
It can hide certain problems you don't want hidden, and C is perfectly capable of implicitly converting the void* return value to any other pointer.
And, of course, you probably want to encapsulate the creation of these vectors to make management of them easier, such as with having the following in a header file vector.h:
#include <stddef.h>
struct Vector {
double *data; // Use readable names rather than x/n.
size_t size;
};
struct Vector *newVector(size_t sz);
void delVector(struct Vector *vector);
//void setVectorItem(struct Vector *vector, size_t idx, double val);
//double getVectorItem(struct Vector *vector, size_t idx);
Then, in vector.c, you have the actual functions for managing the vectors:
#include <stdlib.h>
#include "vector.h"
// Atomically allocate a two-layer object. Either both layers
// are allocated or neither is, simplifying memory checking.
struct Vector *newVector(size_t sz) {
// First, the vector layer.
struct Vector *vector = malloc(sizeof (struct Vector));
if (vector == NULL)
return NULL;
// Then data layer, freeing vector layer if fail.
vector->data = malloc(sz * sizeof (double));
if (vector->data == NULL) {
free(vector);
return NULL;
}
// Here, both layers worked. Set size and return.
vector->size = sz;
return vector;
}
void delVector(struct Vector *vector) {
// Can safely assume vector is NULL or fully built.
if (vector != NULL) {
free(vector->data);
free(vector);
}
}
By encapsulating the vector management like that, you ensure that vectors are either fully built or not built at all - there's no chance of them being half-built.
It also allows you to totally change the underlying data structures in future without affecting clients. For example:
- if you wanted to make them sparse arrays to trade off space for speed.
- if you wanted the data saved to persistent storage whenever changed.
- if you wished to ensure all vector elements were initialised to zero.
- if you wanted to separate the vector size from the vector capacity for efficiency(1).
You could also add more functionality such as safely setting or getting vector values (see commented code in the header), as the need arises.
For example, you could (as one option) silently ignore setting values outside the valid range and return zero if getting those values. Or you could raise an error of some description, or attempt to automatically expand the vector under the covers(1).
In terms of using the vectors, a simple example is something like the following (very basic) main.c
#include "vector.h"
int main(void) {
struct Vector *myvec = newVector(42);
myvec->data[0] = 2.718281828459;
delVector(myvec);
}
(1) That potential for an expandable vector bears further explanation.
Many vector implementations separate capacity from size. The former is how many elements you can use before a re-allocation is needed, the latter is the actual vector size (always <= the capacity).
When expanding, you want to generally expand in such a way that you're not doing it a lot, since it can be an expensive operation. For example, you could add 5% more than was strictly necessary so that, in a loop continuously adding one element, it doesn't have to re-allocate for every single item.
The first time around, you allocate memory for Vector, which means the variables x,n.
However x doesn't yet point to anything useful.
So that is why second allocation is needed as well.
How can malloc allocate structs?
c - Do we have to malloc a struct? - Stack Overflow
Question regarding struct, String and Malloc
Structs???? Malloc??? Pointers to Malloc and Structs??
Videos
I am currently on lecture 5 of cs50 course. So in it while implementing linked lists, after declaring a struct called "node", we malloc a node..like this:
node *n = malloc(sizeof(node));
And then after that, we treat it as if n is actually pointing to a node and we use operations like
n->Number and n->Next
But malloc only really allocates the amount of memory needed for a node right? We have not yet properly declared a node like we declare other structures like int v = 10 or char l = 'j';
Im sorry but I got slightly confused on this part..
A struct can be allocated automatically, but you are using a pointer to struct which will not allocate space for the destination struct. So that's the reason you get segfault.
The reason your initialization is incorrect is that you are initializing struct members, not the struct itself. Also you are doing this in a wrong way.
There are 2 ways for initializing a struct :
Using stack allocated
struct:struct example { int foo; }; int main() { struct example e; e.foo=1; }Using heap allocated
structwith help ofmalloc():struct example { int foo; }; int main() { struct example *e=malloc(sizeof(struct example)); e->foo=1; }
Please note that when you are assigning value to a member of a struct from its pointer (heap allocated struct) you have to use '->' but for the normal struct (the stack allocated one) you have to use '.' .
Your assumption is correct: a pointer hasn't memory for the object it is supposed to point on its own, you need to allocate it yourself.
Anyway, as juanchopanza noted: you don't need a pointer and a memory allocation if you're dealing with a local object.
Both techniques follow:
typedef struct Node {
void* data;
int ref;
struct Node* next;
} Node;
typedef struct Node* NodePtr;
int main() {
NodePtr node = (NodePtr)malloc(sizeof(Node));
node->data = 0;
node->next = 0;
node->ref = 42;
printf("%d", node->ref);
Node obj = {0,42,0}; // this is not on the heap
printf("%d", obj.ref);
The other syntaxes you tried are not correct. Not even part of the language.