Search code examples
cobjecttypessize

C - How to declare an object type of arbitrary byte size?


I want to loop over arrays in a type-independent manner by casting a void pointer to an array of objects of arbitrary byte size. I know the size of the array and the size of its items, but not the type of the items. Is there a safe and portable way of doing this?

All I can think of at the moment is to create a struct with one member, a char array of the required size. But I'm not sure how safe and portable this is as a solution, due to possibility of alignment issues and possibly other problems I haven't thought of.

Example code of what I want to do:

void myFunc(void * arrV, int len, size_t arrSize, size_t itemSize) {
  // type definition, for array item of size itemSize
  struct xxxx {char[itemSize];};
  struct xxxx * arr = (struct xxxx *) arrV;
  for (int i = 0; i < len; i++) {
    if (i == 100) {
      struct xxxx arrItem = arr[i];
      // do something with arrItem;
    }
  }
}

Edit: question title edited as it was phrased incorrectly.


Solution

  • I want to loop over arrays in a type-independent manner by casting a void pointer to an array of objects of arbitrary byte size. I know the size of the array and the size of its items, but not the type of the items. Is there a safe and portable way of doing this?

    It depends on how portable you need it to be. Your suggestion of an defining a structure type containing an array of the desired length is not viable for two reasons:

    1. In standard C, structure types may not be defined as containing variable-length arrays, and

    2. There is no portable way to ensure that the structure type would not contain padding (which would make its size wrong).

    Additionally, the variable-length array feature is optional in C11 and C17 (though it is a mandatory in C99, and some form of it might return to mandatory status in C2X). But if you are willing to rely on VLAs then you can use them more directly for your purpose:

    void myFunc(void *arrV, int len, size_t arrSize, size_t itemSize) {
        char (*items)[itemSize] = arrV;  // pointer to (variable-length) array
    
        for (int i = 0; i < len; i++) {
            // ... do something with items[i] ...
        }
    }
    

    If you don't want to depend on VLAs then the conventional way that functions such as qsort() do it is to convert the void * to a char * and perform appropriate arithmetic with that:

    void myFunc(void *arrV, int len, size_t arrSize, size_t itemSize) {
        char *items = arrV;
    
        for (int i = 0; i < len; i++) {
            char *item_start = items + (i * itemSize);
            // ... do something with *item_start
        }
    }