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.
c - Do we have to malloc a struct? - Stack Overflow
How to properly malloc for array of struct in C - Stack Overflow
How can malloc allocate structs?
When to use Malloc
Videos
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.
Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:
struct line* array = malloc(number_of_elements * sizeof(struct line));
In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().
Note that's it's better style to use:
sizeof(*array)
instead of:
sizeof(struct line)
The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.
Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:
typedef struct line
{
char* addr;
char* inst;
} line;
You can then just do:
line* array = malloc(number_of_elements * sizeof(*array));
Of course don't forget to also allocate memory for array.addr and array.inst.
For what you have described, You do not need to allocate memory for your struct, rather, you need to allocate memory for the members char *addr;, and char *inst;. If you want to have a single copy of that structure, the first section of code illustrates how to initialize, and assign values. If you want an array, the second code example illustrates the differences.
This illustrates how to allocate memory for the members of a single struct line:
typedef struct
{
char* addr;
char* inst;
}LINE;
LINE line;
int main(void)
{
strcpy(line.addr, "anystring"); //will fail
line.addr = malloc(80);
line.inst = malloc(80);
strcpy(line.addr, "someString");//success;
strcpy(line.inst, "someOtherString");//success;
}
For array of struct line...
typedef struct
{
char* addr;
char* inst;
}LINE; //same struct definition
LINE line[10]; //but create an array of line here.
int main(void)
{
int i;
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
//when done, free memory
for(i=0;i<10;i++)
{
free(line[i].addr);
free(line[i].inst);
}
}
Added to address comment
Addressing the comment under this answer from @Adam Liss, the following code illustrates the following improvements using strdup(): 1) Uses only memory needed. 2) Performs memory creation and copy operations in one step, so the the following blocks:
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
Become:
for(i=0;i<10;i++)
{
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
}
One more note: Error handling was not included in examples above to avoid muddling up focus on the main concepts: But for the sake of completeness, because both malloc() and strdup() can fail, actual usage for each of these two functions, should include a test before using, eg:
Rather than
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
The code should include
line[i].addr = strdup("someString");
if(!line[i].addr)
{
//error handling code here
}
line[i].inst = strdup("someOtherString");
if(!line[i].inst)
{
//error handling code here
}
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..