Struct with combined static and dynamic char array

I am creating a dynamically distributed linked list in which each item has a data item. Most of these elements are arrays with a fixed char size, but some may have different lengths, for example. only 1 or 2 characters - or 1000 +.

If I use union inside a data element with a static and dynamic char array - it will always occupy:

  • static size, or if malloc'd size malloced?
  • static size one + if malloc'd size malloced?
  • malloced pointer size or static size?
  • ... (etc.)

A simplified example without a list. This is not how I populate it with data - just as an example of a union structure.

#include <stdio.h> #include <stdlib.h> #include <string.h> enum meta_type {LIST, STRING}; struct meta { union { char clist[128]; char *cstr; } val; enum meta_type type; }; int init_meta(struct meta *meta, enum meta_type type, int size, char *data) { if (type == STRING) { if ((meta->val.cstr = malloc(size + 1)) == NULL) { puts("Out of memeory"); return 1; } sprintf(meta->val.cstr, "%s", data); } else { memset(meta->val.clist, 0, 128); meta->val.clist[0] = data[0]; meta->val.clist[1] = data[1]; meta->val.clist[2] = data[2]; } meta->type = type; return 0; } void free_meta(struct meta *meta) { if (meta->type == STRING) free(meta->val.cstr); } int main(int argc, char *argv[]) { struct meta meta; char list[] = {'a', '3', 'f'}; if (argc > 1) { if(init_meta(&meta, STRING, strlen(argv[1]), argv[1])) return 1; } else { init_meta(&meta, LIST, 0, list); } fprintf(stdout, "meta[%d]: %s\n", meta.type, meta.type == LIST ? meta.val.clist : meta.val.cstr ); free_meta(&meta); return 0; } 

@Floris: One of the good ways I tested:

 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> enum meta_type {LIST, STRING}; #define SIZE_CLIST 128 struct meta { enum meta_type type; union { char clist[SIZE_CLIST]; char *cstr; } val; }; int init_meta(struct meta **meta, enum meta_type type, int size, char *data) { if (type == STRING) { if (offsetof(struct meta, val) == 0) { puts("Ups."); return 2; } *meta = malloc(sizeof(struct meta) - SIZE_CLIST + sizeof(char *) ); (*meta)->val.cstr = malloc(size + 1); if ((*meta)->val.cstr == NULL) { puts("Out of memeory"); return 1; } sprintf((*meta)->val.cstr, "%s", data); puts((*meta)->val.cstr); } else { *meta = calloc(1, sizeof(struct meta)); (*meta)->val.clist[0] = data[0]; (*meta)->val.clist[1] = data[1]; (*meta)->val.clist[2] = data[2]; } (*meta)->type = type; return 0; } void free_meta(struct meta *meta) { if (meta->type == STRING) free(meta->val.cstr); free(meta); } int main(int argc, char *argv[]) { struct meta *meta = NULL; char list[] = {'a', '3', 'f'}; if (argc > 1) { if(init_meta(&meta, STRING, strlen(argv[1]), argv[1])) return 1; } else { init_meta(&meta, LIST, 0, list); } fprintf(stdout, "meta[%d] %d: %s\n", meta->type, sizeof(*meta), meta->type == LIST ? meta->val.clist : meta->val.cstr ); free_meta(meta); return 0; } 
+4
source share
1 answer

The union will set aside space for the largest member. You have an array and a pointer, so it will allocate space for the array. The pointer is fixed in size, it does not matter what it points to.

When you use malloc , the space is not allocated inside the data structure, it is somewhere else in memory. You assign this memory to a pointer.

+1
source

All Articles