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.
My favorite:
#include <stdlib.h>
struct st *x = malloc(sizeof *x);
Note that:
xmust be a pointer- no cast is required
- include appropriate header
You're not quite doing that right. struct st x is a structure, not a pointer. It's fine if you want to allocate one on the stack. For allocating on the heap, struct st * x = malloc(sizeof(struct st));.
Allocate memory for a struct with a character pointer in C - Stack Overflow
c - Structs, pointers and memory allocation - Stack Overflow
c - Allocating memory to a struct using pointers - Stack Overflow
Best practice on allocating memory for a struct that has dynamic array members
Videos
You are allocating only memory for the structure itself. This includes the pointer to char, which is only 4 bytes on 32bit system, because it is part of the structure. It does NOT include memory for an unknown length of string, so if you want to have a string, you must manually allocate memory for that as well. If you are just copying a string, you can use strdup() which allocates and copies the string. You must still free the memory yourself though.
mystruct* structptr = malloc(sizeof(mystruct));
structptr->word = malloc(mystringlength+1);
....
free(structptr->word);
free(structptr);
If you don't want to allocate memory for the string yourself, your only choice is to declare a fixed length array in your struct. Then it will be part of the structure, and sizeof(mystruct) will include it. If this is applicable or not, depends on your design though.
Add a second malloc for whatever length (N) you need for word
mystruct* structptr = malloc(sizeof(mystruct));
structptr->word = malloc(sizeof(char) * N);
It seems, nr is an array of int and not just int. Fix it's declaration:
typedef struct {
int * nr;
char *nume, **mesaj;
} utilizator;
If you only want one int, don't call malloc. It will be allocated as part of your utilizator object (funny word btw).
First, you do not need to user->nr = malloc (n * sizeof(int)); because nr is just an int and it have its own memory space of length sizeof(int) bytes.
Secondly and most important,
You are not including the header file
#include <stdlib.h>. Beacuse of this, the malloc function is implicitly declared to return int. Since you are treating the result as a pointer, there is a type-mismatch warning there.
All you have to do is, include the file stdlib.h.
void* will be safely promoted to any other pointer type in this case.
So, your code should be something like this::
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int nr;
char *nume, **mesaj;
} utilizator;
void citire_mesaje(utilizator *user, int n)
{
scanf("%d", &user[0].nr);
printf("user[0].nr = %d\n", user[0].nr);
return ;
}
int main()
{
int n = 0 ;
utilizator *user = malloc (sizeof(utilizator));
citire_mesaje(user, n);
free( user ) ;
return 0;
}
Hi all! I am very new to C but am familiar with Python & Go quite a bit. Memory allocation is a new concept to me, but I want to start with best practices.
Lets say I want to create a struct that has some members, where one of them happens to be a pointer which I will size dynamically as an array.
Here is what I am doing in my init_my_struct(int n) function. I want to understand if I am doing something that is bad practice here
#include <stdlib.h>
#include <stdio.h>
struct my_struct {
int n;
int *my_arr; // this will be dynamically grown based on user arg
};
struct my_struct * init_my_struct(int n)
{
// allocate memory for one struct
struct my_struct *ms = malloc(sizeof(struct my_struct));
// use -> syntax since ms is a pointer
ms->n = n;
ms->my_arr = malloc(sizeof(int)*n);
return ms;
}
int main(int argc, char *argv[])
{
if (argc < 2) return 1;
int n = atoi(argv[1]);
// initialize the struct members
struct my_struct *ms = init_my_struct(n);
// check out contents of my struct
printf("my struct's n: %d\n", ms->n);
printf("my struct's my_arr: \n");
for (int i = 0; i < n; i++) {
printf("%d\n", ms->my_arr[i]);
}
free(ms); // clean up the memory
return 0;
}Any pointers or tips would be great! Thank you!
What you have created in your example is an array of particle, and another array of pointers to particle. Your first loop fills data into both arrays so that the pointer located in pp[i] points to the particle in list[i].
If your question means "should I always allocate memory to accommodate a pointer to a struct" means "should I always run malloc to make space for every struct pointer I create," the answer is "no," as your code demonstrates. A non-NULL pointer should point to some valid memory space. Very often, you allocate new space immediately by calling malloc. But you can also make the pointer point to space that already exists and is in use. In your case, space from your first array, which is now effectively shared.
Make sure when you run free, you send it exactly the values you got from malloc, exactly one free for each malloc.
In either case, be careful and draw yourself a picture of it so you know what's going on.
A pointer needs 4 bytes (32 bit machine) or 8 bytes (64 bit machine). If you are creating a list of pointers, you should definitely allocate memory to that list and then store those pointers. The short answer you should always allocate memory to accommodate any type of pointer (whether it is normal or it points to a struct) because structure does not claim any memory for itself .
struct c c1;
c1.name = "Ana";
You don't have allocate memory here because you are making the pointer c1.name point to a string literal and string literals have static storage duration. This is NOT similar to:
char name[] = "Anna";
Because in this case memory is allocated to store the sting literal and then the string literal "Anna" is copied into the array name . What you do with the struct assignment c1.name = "Ana" is similar to when you do:
char *name = "Anna";
i.e. make the pointer point to a string literal.
I am new to C but from what I think this could be just the same as
char *cThing;
cThing = "Things!";
where printf("%s\n", cThing); would then print "Things!", except you're declaring the pointer in a struct.
If you insist on passing the pointer, it should be by reference, so it's a pointer to a pointer, as the function itslef will modify the address in the pointer.
You're much better off if your function returns a pointer.
//function for allocating the memory
myName *structMemInit(void)
{
myName *myNameIs = (myName *)calloc(1, sizeof(myName));
if (myNameIs == NULL) {
printf("allocating memory didn't work!\n");
exit(1);
} else { // don't repeat the negation of the condition
myNameIs->name = "Zach"; // No need for \0, it's automatic
return myNameIs;
}
}
//Usage
myName *myNameIs = structMemInit();
BTW it's int main(void) not int main().
Before I answer, I should state that I am not too well-versed in C, I am a C++ programmer so there may be a few grammatical errors in what follows. Hopefully though, my point will be made sufficiently for any errors to be of much importance.
The reason you're getting segfault is because of your misunderstanding of what's happening when you pass a pointer as an argument to a function.
Imagine, for instance, your program was the following:
int main(void){
int i;
setInteger(i);
printf("%d\n", i);
return 0;
}
void setInteger(int n){
n = 12;
}
In this case, you can clearly see that the output will be undefined because the variable i was not initialised, and was passed by-value to setInteger. Any changes to n are not transferred back to i when the function returns.
If the program were replaced with
int main(void){
int i;
setInteger(&i);
printf("%d\n", i);
return 0;
}
void setInteger(int *n){
*n = 12;
}
Then the value output by i will be 12.
The same thing is happening in your program, you're passing your pointer by value.
If you want to pass by reference, you need to do the following:
int main(void){
myName *myNameIs;
structMemInit(&myNameIs); // pass the address of your pointer
printf("%s\n", myNameIs->name);
return 0;
}
//function for allocating the memory
void structMemInit(myName **myNameIs){ // argument is pointer-to-pointer
*myNameIs = (myName *) calloc(1, sizeof(myName)); // dereference pointer to get underlying pointer
if(*myNameIs == NULL){
printf("allocating memory didn't work!\n");
exit(1);
}
else{
*myNameIs->name = "Zach";
}
}
That's, unfortunately, not the end of your problems. Although you've allocated memory to your myName object, you have not allocated memory to your character array.
To return the string "Zach", you need to do the following:
*myNameIs->name = (char*)malloc(5*sizeof(char)); // need extra char for \0
strcpy(*myNameIs->name, "Zach");