1

If I have a long char array[100], which store a list of structs in it, and if I want to add one one struct in the end, how do I check if it exceeds the boundary or not?

For example,

static char arr[100];
typedef NODE* node_ptr;

typedef struct node
{
   char a;
   char b;
   int size;
   node_ptr next;
}NODE;

//arr already contains few node in it.

//size: the new node size, I want to add in the end
node_ptr add_node(node_ptr last, size_t size)
{
    node_ptr new;
    if(last+2*sizeof(NODE)+size<arr+100)
         //add new node
       return new;
}

enter image description here

How can I check if new node exceed the array boundary?

Boba
  • 87
  • 10
  • It doesn't make sense to try to store the type Node or pointer to Node in an char array. You would instead declare an array of type Node or Node*. static Node* arr[100]; arr[0] = malloc(sizeof(Node)); – Outrageous Bacon Oct 13 '20 at 17:50
  • 3
    (a) You should not be storing structures inside an array of `char` because structures often have alignment requirements greater than one byte due to the members inside them, but the compiler may assign any location to your array of `char` because `char` has an alignment requirement of only one byte. So, when you store a structure in the array, it may be at an invalid alignment, which can cause your program to abort/fault or have other problems. – Eric Postpischil Oct 13 '20 at 17:50
  • 1
    @OutrageousBacon: Some embedded system provide no malloc function. So it can make sense to manually manage allocation. – Serge Ballesta Oct 13 '20 at 17:51
  • 2
    (b) You should not be storing structures inside an array of `char` because C has rules about what behaviors are defined for using objects of one kind as if they were another kind, and those rules do not define the behavior for using an array of `char` for structures. The compiler optimizer may optimize your program based on the rules in the C standard, and that could break your program. – Eric Postpischil Oct 13 '20 at 17:52
  • 1
    (c) That said, if a `char *` named `p` points to the point in, or just at the very end of, `arr` where you intend to put the next structure, say `struct foo`, then if `sizeof arr < p-arr + sizeof(struct foo)`, the structure will not fit. (Note: In spite of (a) and (b) above, you **can** copy the bytes of structures into the array for temporary storage or for sending over a network or other communication medium, and you can copy the bytes out again into proper space for the structures to reconstitute them, as long as you do not use the data inside the array as if it were the actual structures.) – Eric Postpischil Oct 13 '20 at 17:54
  • @OutrageousBacon I tried to write my own malloc function and using this char array as simulated memory – Boba Oct 13 '20 at 17:55
  • @EricPostpischil is p-arr an address? can I compare an address and sizeof arr – Boba Oct 13 '20 at 17:59
  • 1
    @AKu: Whether it is conformant to write a malloc function in plain C from a char array is not clear, even if it is accepted by all compilers I know. But it must at least meet all the requirements of a true `malloc` and ensure that the returned memory block is suitable for any standard alignment. – Serge Ballesta Oct 13 '20 at 17:59
  • 2
    @AKu: If you want to write your own allocation functions for experimental/learning purposes, then define the array to have the necessary alignment, as with `static char _Alignas(max_align_t) arr[100];`, and include `` to get the definition of `max_align_t`. Write the allocation functions to always return space allocated to a multiple of `_Alignof(max_align_t)`. Put the functions in a separate translation unit. For normal compilers, without inter-unit optimization features, putting the functions in a separate unit is a kludge to deal with the aliasing issue described in (b). – Eric Postpischil Oct 13 '20 at 18:01
  • 1
    @AKu: `p` is a pointer, `arr` is an array, and `p-arr` is a subtraction that produces the number of elements (bytes in this case) between where `p` points and where `a` starts. – Eric Postpischil Oct 13 '20 at 18:02
  • @SergeBallesta can I align the block manually? like the size and the node both are multiple of eight. – Boba Oct 13 '20 at 18:03
  • @EricPostpischil can I do `p = (last+1)+last->size` to get the p pointer? – Boba Oct 13 '20 at 18:09
  • 1
    You can also define your struct so that no padding is inserted in order to ensure alignment: defining it as a [packed structure](https://stackoverflow.com/a/5473235/11336762). Search for something like `packed` or `_packet` in your compiler manual. In this way storing into a char array should work, and you'll save space for data, but it will be slower. – Roberto Caboni Oct 13 '20 at 18:10
  • 2
    Although this is a subjective opinion, things like `typedef NODE* node_ptr;` do tend to be more of a nuisance than a help. If I read `NODE*` I know it's a pointer to a `NODE`. If I see `node_ptr` then it's a...pointer to a...`node`? Which is wrong. You've made a shorthand notation which is actually longer. Just use `NODE*`. – tadman Oct 13 '20 at 18:11
  • Your add_node should return NULL if the node does not fit. – stark Oct 13 '20 at 19:33

1 Answers1

0

this is COMMENT

do not upvote - but feel free to DV.

You ask difficult question and it is not easy to answer. You need also to consider some more complex cases like

enter image description here

or enter image description here

or enter image description here

Small array will become fragmented in a very short time. This is one of the reasons why uC developers try to avoid this kind of memory allocation. There are other techniques like pools used in the embeedded programming.

0___________
  • 60,014
  • 4
  • 34
  • 74