OK, so I've got the following C code:
//for malloc
#include <stdlib.h>
//to define the bool type
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef int bool;
#endif
//define structs
typedef struct A{
int integerValue;
char characterValue;
} A;
typedef struct B{
float floatValue;
bool booleanValue;
} B;
int main(int argc, const char * argv[])
{
//allocate a void pointer array
void* myArray[3];
//fill the array with values of different struct types
myArray[0] = malloc(sizeof(A));
myArray[1] = malloc(sizeof(B));
myArray[2] = malloc(sizeof(A));
}
but I want to be able to dynamically resize the array. I know that you can dynamically resize an array containing just one type like this:
int* myArray;
myArray = malloc(3*sizeof(int));
myArray[0] = 3;
myArray = realloc(myArray,4*sizeof(int));
printf("%i",myArray[0]);
but how would you do this in the upper situation (it needs to be able to handle a virtually infinite number of types). Would it work to reallocate the array with realloc(myArray,newNumberOfIndices*sizeof(ElementWithBiggestSize)), or is there a more elegant way to achieve this?
B* b_pointer = (B*) malloc (sizeof(B*));
void** arr = (void**) malloc (3 * sizeof(void*));
arr[0] = b_pointer;
void** new_arr = (void**) malloc (6 * sizeof(A*));
memcpy(new_arr, arr, 3 * sizeof(A*));
// now arr[0] == new_arr[0] == b_pointer;
free(arr);
// now new_arr[0] == b_pointer;
Note that if you're allocating pointers, it doesn't really matter which struct or array (or i don't know what) you want to point to.
PS: happy debugging using void pointer array with different structs
edit: renaming "b_instance to b_pointer", just trying to make it less confusing
Related
I've got a struct definition,
struct liste{
unsigned int size;
unsigned int capacity;
char* data;
};
and an instance,
struct liste lst = {3, 4, "hi"};
and what I'm trying to do is get the data member without directly calling lst.data. So far I've been able get a pointer, dataC ;
char* dataC = (char *) ((char *)&lst + 2 * sizeof(unsigned int));
whereby printing dataC and &lst.data as pointers gives the same output. I thought dereferencing dataC and casting the result to a char * would yield a pointer identical lst.data but I get a segfault.
Is there something I'm missing??
According to your code, dataC does not store the address of the data "hi", but the address of the pointer of lst.data. You can see the code below. dataC is the address of lst.data. *dataC is the address of the string "hi", the same as lst.data.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<stdint.h>
struct liste{
unsigned int size;
unsigned int capacity;
char *data;
};
int main()
{
struct liste lst = {3, 4,"hi"};
char **dataC = (char **) ((char *)&lst + 2 * sizeof(unsigned int));
printf("datac = %s\n",(*dataC));
}
Your code is neither portable nor rugged, because there might be struct padding inside the struct. If you need to do something like you attempt here, you should be using the offsetof macro, which is used to get the byte offset of a member inside a struct. Example:
#include <stdio.h>
#include <stddef.h> // offsetof
struct liste{
unsigned int size;
unsigned int capacity;
char* data;
};
int main (void)
{
struct liste lst = {3, 4, "hi"};
char** ptrptr = (char**) ((char*)&lst + offsetof(struct liste, data)) ;
puts(*ptrptr);
}
Notably the (char*)&list part has nothing to do with the data we are looking for being of char type. This is simply a way of iterating through a larger data type byte by byte, which C allows if we use character pointers. We end up with a character pointer pointing at the location of (the pointer) data inside the struct. By casting the result to char**, we make it clear that whatever we are pointing at is a char*.
Similarly, we could get the capacity member like this:
unsigned int** pp_cap = (unsigned int**) ((char*)&lst + offsetof(struct liste, capacity)) ;
printf("%d\n", *pp_cap);
I've got a struct to say:
struct mystruct {
int *myarray;
}
In my main function, I want to assign to "myarray" the values of a predefined array.
int main(){
int array[5] = {1,2,3,4,5};
//how to "assign" array values to myarray ?;
}
I would like avoid making a cycle of an assignment like :
struct mystruct str = malloc(sizeof(mystruct));
for(int i = 0;i<size_of_array;i++){
str->myarray[i] = array[i];
}
is this possible?
struct mystruct {
int *myarray;
}
here myarray is just a pointer to memory. There is no space reserved there, so your example will fail.
You have two options:
Just use the array you already have, this assumes the array is not free'd before the structure is free'd:
instance->myarray = array;
reserve memory and memcpy the data
instance->myarray = malloc(sizeof(int) * 5);
memcpy(instance->myarray, array, sizeof(int) * 5);
you can try memcpy
struct->array = malloc(sizeof(some_array));
memcpy(struct->array, some_array, sizeof(some_array));
and for your case this is
str->array = malloc(sizeof(array));
memcpy(str->array, array, sizeof(array));
Consider:
typedef struct test
{
int i;
char c[2][5];
} test;
This can be initialized using:
test t = {10, {{'a','b','c','d','\0'}, { 0 }}};
// or
test t = {10, {{'a','b','c','d','\0'}, {'x','y','z','v','\0'}}};
I'm new to programming and to C, and I just learned about structs. I'm trying to use them to make an array which can change size as required (so, if the array gets full, it creates a new array double the size, copies the old array into the new one and deletes the old one). All I've done so far is create the struct and the functions for setting it up, and already I'm having problems. The main problem is that, sometimes when I run it it does exactly what I expect it to, which is create the struct, return a pointer to said struct, and then print all elements of the contained array. Other times when I run it, it does nothing at all! I don't get how it can work sometimes, and sometimes not! Obviously i'm doing something really wrong, but I can't work out what. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int cap;
int used;
void (*cpy) (int *, const int *, int);
//void (*append) (int);
int array[];
} dynArray;
dynArray * new_dynArray(int *, int);
void copy(int *, const int *, int);
int main(void) {
int start_arr[] = {1,2,3,4,5,6};
// create new dynArray, pass start array and number of elemnts
dynArray *arr = new_dynArray(start_arr, \
sizeof(start_arr) / sizeof(start_arr[0]));
// print all elements of dynArray
for (int i=0; i<(arr->used); i++) {
printf("%d, %d\n", arr->array[i], i);
}
free(arr);
return 0;
}
dynArray * new_dynArray(int init_arr[], int size) {
//printf("%d", size);
// if number of elements >= 4 then dynArray size is double, else 8
int init_cap = (size >= 4) ? 2 * size : 8;
// create pointer with enough space for struct and the actual array
dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + init_cap );
arr->cap = init_cap;
arr->used = size;
// assign address of funciton copy to arr->cpy
arr->cpy = copy;
// call the function, to copy init_arr to arr->array
arr->cpy(arr->array, init_arr, size);
return arr;
}
void copy(int dest[], const int src[], int src_size) {
// just copy initial array to new array
int i;
memcpy(dest, src, src_size*sizeof(int));
/*
for (i=0; i<src_size; i++) {
dest[i] = src[i];
printf("%d\n", dest[i]);
}*/
}
So I call init_dynArray, sending a normal array and the number of elements in the array. init_dynArray uses malloc to create space in memory for the struct + the inintal size of the array, set up everything in the struct and copy the array, and then return a pointer to it. I don't get how it can only work some of the time. Hope yuo guys can help, thanks!
The problem in your code is on this line:
dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + init_cap );
You need to multiply init_cap by sizeof(int)
dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + sizeof(int)*init_cap );
You should also use size_t for the init_cap's type.
Note: Storing a pointer to the copying function inside the struct would be useful if your dynamic array consisted of opaque elements that require non-trivial copying. Since copying ints can be accomplished with a simple memcpy, there is no need to store a function pointer in dynArray.
I have this struct definition:
typedef struct intArray
{
int myArray[1000];
} intArray;
My goal is to create an intArray of zeros, i tried this:
intArray example;
int createArray[1000] = {0};
example.myArray = createArray;
This results in this error message:
error: assignment to expression with array type
I want the struct to automatically initialize the array to 0's but i understand it is not possible because it is only a type definition and not a variable. So i created one and created the array, just tried to assign it and this is the result. Any advice is appreciated.
Why not use memset to zero the array? Also, as suggested by another user, it'd be better to allocate this memory to a pointer....especially if you intend to pass that struct around between functions.
Just a thought, but this would work:
typedef struct intArray {
int *myArray;
} intArray;
int main(void)
{
intArray a;
int b;
// malloc() and zero the array
//
// Heh...yeah, always check return value -- thanks,
// Bob__ - much obliged, sir.
//
if ((a.myArray = calloc(1000, sizeof *a.myArray)) == NULL) {
perror("malloc()");
exit(EXIT_FAILURE);
}
memset(a.myArray, 0, (1000 * sizeof(int)));
// Fill the array with some values
//
for (b = 0; b < 1000; b++)
a.myArray[b] = b;
// Just to make sure all is well...yep, this works.
//
for (b = 999; b >= 0; b--)
fprintf(stdout, "myArray[%i] = %i\n", b, a.myArray[b]);
free(a.myArray);
}
Declaring arrays like int myArray[1000]; won't let you change the value of the array pointer. Declare your struct like
typedef struct intArray
{
int *myArray;
} intArray;
if you can.
I can't quite figure out how to do this, I've tried this and several variations and some will compile and seemingly work ok but I'll get very random segfaults and it has something to do with the way I'm declaring these structs. All the info in the structs are dynamic. Please let me know the proper way to do this, thank you.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char* s2string1;
char* s2string2;
int s2int1;
} struct2;
typedef struct
{
char* s1string1;
char* s1string2;
struct struct2* mystruct;
int int1;
} struct1;
struct struct2* RetS2(char* CopyMe)
{
int* Array = (int*) malloc (sizeof (int) * 5);
Array[0] = strlen (CopyMe);
struct struct2* S2 = (struct struct2*) malloc ( sizeof (struct2) );
S2->s2int1 = Array[0];
return S2;
}
struct struct1* RetS1()
{
struct struct1* S1 = (struct struct1*) malloc ( sizeof (struct1) );
struct struct2* S2 = RetS2();
S1->mystruct = S2;
S1->int1 = S2->S2int1;
return S1;
}
int main()
{
struct struct1 Top = RetS1();
if (Top->mystruct->s2int1 == 10)
// do something
return 0;
}
Your code has multiple issues:
This is the main issue:
RetS2's function definition is
struct struct2* RetS2(char* CopyMe)
which means that it expects a char* as its first argument. But when you call it:
struct struct2* S2 = RetS2();
you don't pass an arguments. This invokes Undefined Behavior.
Here:
int* Array = (int*) malloc (sizeof (int) * 5);
You allocate memory for 5 ints. You use the first element of the array and stops using it. You also forgot the free the allocated memory for Array.
The cast in malloc (and family) is not required in C.
You don't free the malloced memory for S2 and S1.