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 Overflow
Top answer
1 of 8
198

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.

2 of 8
5

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.

๐ŸŒ
Delft Stack
delftstack.com โ€บ home โ€บ howto โ€บ c malloc struct
How to Allocate Struct Memory With malloc in C | Delft Stack
February 12, 2024 - In this method, memory is allocated to store an array of structures using malloc. The following example code demonstrates the case when the array of 100 pointers to the MyObject structs is declared on the stack, but each individual MyObject object is allocated on dynamic memory (heap).
Discussions

c - Do we have to malloc a struct? - Stack Overflow
Learn more about Collectives ... Bring the best of human thought and AI automation together at your work. Explore Stack Internal ... I have found that I am getting segfaults whenever I try to do anything with NodePtr's fields. E.g.: ... So I allocated some space for the NodePtr, and now it seems to work fine. Why is this? My guess is that since node is just a pointer, it has no memory for its fields. ... You don't need malloc. For example, struct ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
How to properly malloc for array of struct in C - Stack Overflow
Also note that there is no reason ... value of malloc(). ... 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 ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
How can malloc allocate structs?
There isn't any further formatting or anything else needed in C to create a variable, you just need a space in memory big enough to hold it and a name that can reference it. The call to malloc reserves a space in memory that will hold your structure and returns a pointer to it, so once that call completes n is a valid pointer to a node structure. The node structure doesn't have valid data in it yet, so we probably want to initialize it to something reasonable with statements like: n->Number = 0; n-Next = NULL; This is exactly what the initializer function in a language like Java or C++ does when you call new Node. In C you need to do those steps yourself. You're also free to skip those steps if they aren't necessary in your context. You're also free to skip those steps when they are necessary and introduce a bug into your program. More on reddit.com
๐ŸŒ r/cs50
2
3
January 2, 2022
When to use Malloc
Read about heap and stack memory. You have a very limited amount of stack memory. Probably about 8MB or so. On my machine: $ ulimit -a data(kbytes) 15728640 stack(kbytes) 8192 ... Simplified, you can view the stack as the "variable space". This is where all your int foo and char bar[256] goes. But if you use malloc char *p = malloc(...);, then you have created a pointer on the stack, that points into this huge "data area" called heap. Also, the heap is scope independent. After you exit your function, the variables on the stack are gone. This is why it's important to call free() on pointers pointing to the heap area before exiting the function (or pass the reference on to somewhere else). Otherwise you loose the reference to this memory - and that's called memory leak :-) It's good practice to not allocate memory within functions, but to expect the caller to hand in a buffer (pointer to heap) and its size. More on reddit.com
๐ŸŒ r/C_Programming
45
53
February 11, 2024
๐ŸŒ
University of Toronto
cs.toronto.edu โ€บ ~heap โ€บ 270F02 โ€บ node31.html
But first, structs and malloc
n1 = (struct node *) malloc(sizeof(struct node)); n2 = (struct node *) malloc(sizeof(struct node)); n3 = (struct node *) malloc(sizeof(struct node)); head = n1; n1->data = 1; n1->next = n2; n2->data = 2; n2->next = n3; n3->data = 3; n3->next = NULL; /* <-- indicates end of list */ malloc allocates ...
๐ŸŒ
Nyu-cso
nyu-cso.github.io โ€บ notes โ€บ 06-struct-malloc.pdf pdf
Struct, malloc Jinyang Li
Conceptual view of a C programโ€™s ... local variables) We will refine this simple view ยท in later lectures ยท Linked list ยท typedef struct { int val; struct node *next; }node; val:5 ยท...
๐ŸŒ
Programiz
programiz.com โ€บ c-programming โ€บ examples โ€บ structure-dynamic-memory-allocation
C Program to Store Data in Structures Dynamically
#include <stdio.h> #include <stdlib.h> ... "); scanf("%d", &noOfRecords); // Memory allocation for noOfRecords structures ptr = (struct course *)malloc(noOfRecords * sizeof(struct course)); for (int i = 0; i < noOfRecords; ++i) { printf("Enter subject and marks:\n"); scanf("%s ...
๐ŸŒ
Linux Hint
linuxhint.com โ€บ array-of-structs-malloc
How to Use Malloc Function to Create Array of Structs โ€“ Linux Hint
Note: We have to use the โ€œtypedef structโ€ in declaring the struct, by using this we do not have to use the keyword โ€œstructโ€ repeatedly. Another thing to be noted is that it can cause the buffer to overflow because we have used the โ€œchar *โ€ inside the malloc argument to declare the size of the emp_name variable.
๐ŸŒ
HowStuffWorks
computer.howstuffworks.com โ€บ tech โ€บ computer software โ€บ programming
Dynamic Data Structures: Malloc and Free - The Basics of C Programming | HowStuffWorks
March 8, 2023 - The (int *) typecast converts the generic pointer returned by malloc into a "pointer to an integer," which is what p expects. The free statement in C returns a block to the heap for reuse. The second example illustrates the same functions as the previous example, but it uses a structure instead ...
Find elsewhere
๐ŸŒ
Tenouk
tenouk.com โ€บ cpluscodesnippet โ€บ usingmallocnstruct.html
The malloc() C function and struct data storage - the dynamic memory allocation
The malloc() C function and struct data storage program example to demonstrate the dynamic memory allocation
๐ŸŒ
W3Schools
w3schools.com โ€บ c โ€บ c_memory_struct.php
C Structures and Dynamic Memory
Note: malloc() allocates uninitialized memory. The content will be undefined until you assign values. If you want memory initialized to zero, you can use calloc(). You can also allocate memory for multiple structs at once, like an array:
๐ŸŒ
Quora
quora.com โ€บ How-do-I-malloc-an-array-of-structs-in-C
How to malloc() an array of structs in C - Quora
Then, [code]struct X *pArray = malloc(sizeof(struct X) * N); if (pArray) { // Access elements using pArray } [/code]Itโ€™s really that simple. You can use pArray with square bracket i...
๐ŸŒ
C-pointers
c-pointers.com โ€บ malloc_ptr โ€บ dp_malloc_ptr โ€บ structures_dp.html
Malloc struct Double pointer - C Pointers Tutorials
(*ptr)[9] 22 *ptr = malloc( 10 * sizeof(struct ABC) ); 23 24 // Step 5.1 : Assign value to structure objects 25 for (int i = 0; i < 10; i++) 26 { 27 (*ptr)[i].a = ++val; 28 } 29 30 // Step 6.1 : Print the value 31 for (int i = 0; i < 10; i++) 32 { 33 printf("(*ptr)[%d].a = %d\n", i, (*ptr)[i].a); ...
Top answer
1 of 3
40

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 :

  1. Using stack allocated struct:

    struct example {
      int foo;
    };
    int main() {
      struct example e;
      e.foo=1;
    }
    
  2. Using heap allocated struct with help of malloc():

    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 '.' .

2 of 3
2

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.

Top answer
1 of 2
37

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.

2 of 2
10

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
  }
๐ŸŒ
Reddit
reddit.com โ€บ r/cs50 โ€บ how can malloc allocate structs?
r/cs50 on Reddit: How can malloc allocate structs?
January 2, 2022 -

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..

Top answer
1 of 2
3
There isn't any further formatting or anything else needed in C to create a variable, you just need a space in memory big enough to hold it and a name that can reference it. The call to malloc reserves a space in memory that will hold your structure and returns a pointer to it, so once that call completes n is a valid pointer to a node structure. The node structure doesn't have valid data in it yet, so we probably want to initialize it to something reasonable with statements like: n->Number = 0; n-Next = NULL; This is exactly what the initializer function in a language like Java or C++ does when you call new Node. In C you need to do those steps yourself. You're also free to skip those steps if they aren't necessary in your context. You're also free to skip those steps when they are necessary and introduce a bug into your program.
2 of 2
2
node *n = malloc(sizeof(node)); |------| |------------------| A B Part A: Here you declare a pointer to a node "We have not yet properly declared a node like we ....." Part B: Here you allocate the memory sufficient to hold the data of a node. After this you have some memory that can hold a node and a pointer that directs you to that memory location. When you then want to see individual elements of that node struct you ask C to go to that location and look at that memory, C knows you are talking about a "node" since you already declared n as a pointer to a node so C knows what to expect to see at that location. This might not be 100% technically correct but I think it is pretty close and that is what makes me grasp pointers and malloc :)
๐ŸŒ
Swarthmore College
cs.swarthmore.edu โ€บ ~newhall โ€บ cs31 โ€บ resources โ€บ C-structs_pointers.php
CS31: Intro to C Structs and Pointers
int *p; p = (int *)malloc(4); // allocate 4 bytes of heap memory and assign addr to p *p = 6; // the heap memory p points to gets the value 6 malloc's return type is a bit odd. It is a void * which means it is a pointer to a non-specific type (or to any type).
๐ŸŒ
Learn C
learn-c.org โ€บ en โ€บ Dynamic_allocation
Dynamic allocation - Learn C - Free Interactive C Tutorial
This tells the compiler that we want to dynamically allocate just enough to hold a person struct in memory and then return a pointer of type person to the newly allocated data. The memory allocation function malloc() reserves the specified memory space.
๐ŸŒ
Danluu
danluu.com โ€บ malloc-tutorial
Malloc tutorial
If our global base pointer is NULL, ... If we can, then we do; if we can't, then we request space and use the new space. void *malloc(size_t size) { struct block_meta *block; // TODO: align size?...
๐ŸŒ
UCSD
cseweb.ucsd.edu โ€บ ~j2lau โ€บ cs5a โ€บ week8.html
Week 8: structs, malloc
February 25, 2002 - after the malloc is done, we have ... malloc a double */ double* dp = (double*) malloc(sizeof(double)); /* malloc an item */ struct item* ip = (struct item*) malloc(sizeof(struct item)); /* * malloc an array of 50 integers - the name of an array is always * a pointer to the first ...
๐ŸŒ
Diveintosystems
diveintosystems.org โ€บ book โ€บ C2-C_depth โ€บ structs.html
2.7. C Structs
Recall that malloc allocates memory from the heap, and local variables are allocated on the stack. Figure 1. The differences in memory layout between a statically allocated struct (data on the stack) and a dynamically allocated struct (data on the heap). Structs can also be defined to have pointer types as field values. For example...