Changing the size of struct after declared - c

I have a code contains this structure
struct mystruct{
int a;
int array[1];
};
Directly, after running the code
I mean I will not declare any variable of that structure,the user will enter a number, for example 6.
What I want is to know how I can change the size of that structure.
Like I declared on this form
struct mystruct{
int a;
int array[6];
};
Then I use normally, like this:
struct mystruct var;
//I do not want to add any code here, to appropriate new form
for(int i=0;i<6;i++)
var.array[i]=0;

The typical way to do something like this in straight C (as opposed to C++) is to have just a pointer member in the struct, to point to the array, and then another member of the struct to indicate the size. This generally requires users of the struct to malloc() the array as needed, and to also set the size member to match. Something like:
struct mystruct
{
int size;
int *array;
};
and:
struct mystruct var;
var.array = malloc(6 * sizeof(int));
var.size = 6;
for (int i = 0; i < var.size; i++)
var.array[i] = 0;
Another common paradigm is a linked list.
Of course, in C++ you could just use a std::vector<int>.

You cannot change the declaration of the struct but if it is a variable length array within a struct that you want you do have an option. Declare your struct as:
struct mystruct{
int a;
int array[0];
};
And then when you want to create an instance with n elements in the array do the following:
struct mystruct *a = malloc(sizeof(struct mystruct) + n * sizeof(int));
This will create a memory region large enough to hold the struct and an array of length n. You can then use the array just as you would any other array:
a->array[1] = 5;
(this example assumes the array has at least 2 elements)
To accomplish what you have in your code example you would want to do something like this:
struct mystruct *var = malloc(sizeof(struct mystruct) + 6 * sizeof(int));
for(int i=0;i<6;i++) {
var->array[i]=0;
}

You cannot change an already declared struct, but you can make a new one as you want by modifying the program. You can't change data structures used in the program on the fly while it is running.

Related

Can you create an array of Structure inside of another structure in C language?

Aim : To create a structure of element having certain properties. Then utilize that structure type by creating it's array in another structure.
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element *ele;
ele = (struct Element *)malloc(n*sizeof(struct Element));
};
What I wish to know is that which part of the code am I not allowed to write while creating a structure.
The common way to do this is:
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element ele[0]; // Make a zero length array
};
struct Sparse* MakeNewSparse(size_t num_ele)
{
struct Sparse* sparse = malloc(sizeof(*sparse) + num_ele*sizeof(struct Element));
return sparse;
}
This works because accessing off the end of a zero-length array is totally legal in C, provided you have allocated memory there.
In this example, we allocate enough space for the struct Sparse, and then enough more contiguous space for the array of struct Element.
After that, accessing element sparse->ele[5] is totally legal.
The line
ele = (struct Element *)malloc(n*sizeof(struct Element));
should not be part of the struct definition - that's something you do at runtime, along these lines:
struct Sparse s; // create new struct Sparse instance
s.n = get_some_size();
s.ele = malloc( s.n * sizeof *s.ele ); // no need for cast
struct in c is syntactically similar with types like int, char, etc. The definition of a struct is for compiler to know how to use variable declared with that struct such as struct Sparse var;. So the definition of a struct is not actually the code itself. It will be used at compile time.
However, malloc() is a function, which will be used at runtime, so it is nonsense to put malloc() in your struct definition.

struct with a dynamic memory array element in c

I am trying to create a struct. One of the elements of the struct is an array that should be able to grow if needed.
I do this:
int COLS=2, ROWS=20;
long int (*array)[COLS] = malloc(sizeof(int[ROWS][COLS]));
struct test{
long int (*arr)[COLS];
};
struct test *s_test = malloc(sizeof(s_test));
s_test->arr = array;
for (int i=0; i<ROWS; i++){
array[i][0]=i;
array[i][1]=i+20;
printf("0:%ld\t1:%ld\n",s_test->arr[i][0], s_test->arr[i][1]);
}
but the compiler says:
test.c:10:14: error: fields must have a constant size: 'variable length array in structure' extension will never be supported
long int (*arr)[COLS];
This works ok:
int COLS=2, ROWS=20;
long int (*array)[COLS] = malloc(sizeof(int[ROWS][COLS]));
long int (*arr)[COLS];
//struct test{
// long int (*arr)[COLS];
//};
struct test *s_test = malloc(sizeof(s_test));
//s_test->arr = array;
arr = array;
for (int i=0; i<ROWS; i++){
array[i][0]=i;
array[i][1]=i+20;
printf("0:%ld\t1:%ld\n", arr[i][0], arr[i][1]); //s_test->arr[i][0], s_test->arr[i][1]);
}
BTW, I, mistakenly forgot to delete the declaration of a struct test (which is not defined now) and the compiler didn't complain...). I will also appreciate a very simple (if possible) explanation of why.
1 - I clearly don't know how to solve this problem.
2 - Does the struct HAS to be a pointer?
3 - Can't the element arr be a pointer to theh 2darray?
Thank you a lot!
Disclaimer: I think long int (*arr)[COLS] (flexible array to pointer to long) is a mistake; but all you need to do to fix it is adjust the type.
That doesn't look quite right. if COLS really is dynamic we need to say:
struct test{
long int (*arr)[];
};
but this is invalid due to the toy example being too small. The stretchy element has to be the last one, but it can't be the only one either. Needs to look like this:
struct test{
size_t nelem; /* I suppose you could have another way of knowing how many */
long int (*arr)[];
};
and you allocate it with a call that looks like this:
struct test *ptr = malloc(sizeof(struct test) + sizeof (long int *) * COLS);
If COLS is really constant, the way to get to compile is to change the declaration of COLS to be a macro, or an enum like so: enum { COLS = 2; };

C struct with array size determined at compile time

How does one build a struct with an array that can be set differently for each struct, ideally by a parameter? The application being a single data type that supports arrays of different, but fixed lengths
My attempt looks somehting like this, which obviously didnt compile:
struct Data_struct(n)
{
int xData[n];
int test;
};
The only method available is to use a flexible array member.
struct Data_struct {
int test;
int xData[];
};
You would then allocate space for this using malloc():
int n = 4;
struct Data_struct *s = malloc(sizeof(struct Data_struct) + n * sizeof(int));
Note that we had to explicitly allocate additional space for the flexible array.
You can dynamically allocate the array
struct Data_struct
{
int * xData;
int test;
};
....
s.xData = calloc(size, sizeof(int))
and remember to free xData when finished
Normally you would define a variable length array at the end of the struct, and then fix up the size at run-time, e.g.
typedef struct
{
int test;
int xData[1];
} Data_struct;
To allocate a struct such as this with a size of n for xData you'd do soemthing like this:
Data_struct * s = malloc(sizeof(Data_struct) + (n - 1) * sizeof(int));
One might call this ugly but here goes. Use a #define
#define foo(n) struct Data_struct##n { int test; int xData[n]; }
foo(20);
struct Data_struct20 abc;
The foo(20) defines a structure with n = 20 characters.
You could use another #define for the allocation of space if you wish.

Dynamically allocated array of structures in C

I just wanted to know if the following works. I have a struct
called foo that is defined as the following:
struct foo {
char name[255];
int amount;
};
During runtime, I need to create an array of the above structures whose size is dependent on a value I receive from a file's input. Let's say this size is k. Will the following code appropriately allocate a dynamically-sized array of structures?
struct foo *fooarray;
fooarray = malloc(k * sizeof(struct foo));
EDIT: If I want to access members of the structures within these arrays, will I use the format fooarray[someindex].member?
That will work (and your accessing is correct). Also, you can guard against size errors by using the idiom:
fooarray = malloc(k * sizeof *fooarray);
Consider using calloc if it would be nice for your items to start out with zero amounts and blank strings, instead of garbage.
However, this is not a VLA. It's a dynamically-allocated array. A VLA would be:
struct foo fooarray[k];
Yes it will.
On failure it will return 0.
And you have to free the memory returned by malloc when you are done with it
You can access the first member:
fooarray[0].name
fooarray[0].amount
The second as:
fooarray[1].name
fooarray[1].amount
etc..
One more different notation can be used in this approach:
struct foo {
char name[255];
int amount;
};
int main (void)
{
struct foo *fooarray;
struct foo *fooptr[5];
unsigned int i = 0;
for (i = 0; i < 5; i++)
fooptr[i] = malloc(1* sizeof(struct foo));
fooptr[2]->name[3] = 'A';
printf ("\nfooptr[2]->name[3]=%c\n",fooptr[2]->name[3]);
}

How to correctly define an array of structures?

i have the following structure:
typedef struct Course {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} Course;
and the following function i need to implement:
void createReport(FILE* courses[], int numOfCourses, FILE* studentFile, char* reportFileName
as you can see i get an array of FILE*, each cell contains different file pointer.
my intention is to create an array that each cell is Course* type, and initialize each cell with a Course struct containing the data read from the courses files.
what is the correct way to declare it inside the function?
do i need to dynamically allocate memory for it, or it can be done in compilation?
i've tried
Course* course_array[numOfCourses] = {NULL};
Course* course_array[numOfCourses] = NULL;
but it won't compile.
thanks for your help
You declare an array of structs the same way you declare an array of ints or FILE *s:
Type variableName[numberOfElements];
Before C99 (and barring compiler specific extensions), creating an array with a variable number of elements on the stack wasn't supported. So make sure that you are targeting the correct standard. In your case, assuming C99 support, the following should work:
Course *course_array[numOfCourses];
Because you intend to initialize each of the elements in the array, there is no need to zero them out.
You would then access the elements like this:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 2;
/* etc. */
Now if you can't assume C99 support, things get a bit more tricky but not much:
Course *course_array = malloc(sizeof(Course *) * numOfCourses);
After that you can access course_array with the same array notation:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 42;
/* etc. */
Once you're doing with the array, you'll need to make sure that you free any of the memory that you allocated:
for (i = 0; i < numOfCourses; i++) {
free(course_array[i]);
}
/* If you malloc'd course_array, then you need this too */
free(course_array);
Course* course_array[numOfCourses] = {NULL};
This is good, but it creates array of Course *. So you need to allocate memory for each pointer in course_array before accessing it.
Something like
course_array[0] = malloc(sizeof(Course));
course_array[0]->course_id = someid;
When you define the array in the first place, you shouldn't need to allocate memory. You're defining the array on the stack, and the elements of the array are just pointers.
I think what you should do is first define the array, and then initialize each element with a malloc call. For example:
Course* course_array[numOfCourses];
for(int i = 0; i < numOfCourses, i++) {
course_array[i] = (Course*)malloc(sizeof(Course));
My favorite way:
typedef struct {
int a;
char b;
float c;
}DATA;
//then use typdef'ed DATA to create array (and a pointer to same)
DATA data[10], *pData;
//then, in function, you can initialize the pointer to first element of array this way:
int main(void)
{
pData = &data[0];
return 0;
}
Your example code would look like this:
typedef struct {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} COURSE;
//then in function:
COURSE course[numOfCourses]

Resources