0

I have two data types with different-sized fields of the same name. I am trying to access these fields based on a parameter I pass in to a function--- say

struct smallindex
{
   unsigned char index;
   unsigned int count;
};
struct largeindex
{
   unsigned int index;
   unsigned long count;
};

This is possibly not an ideal thing to do-- but one way to implement this is, to have the function treat a pointer as a pointer of different sizes. Say, something like:

void function(int index, void *ptr)
{
   array[] = {struct smallindex, struct largeindex};
   array[index] *pointer = *ptr;
   *pointer[1].index++;
   return;
}

However, the compiler does not like this at all. I tried several other implementations-- but none of them worked. The variability in the bit field size prevented me from trying a union. Is this doable?

Alternatively, if I pad the index sizes to make sure their size matches (but their positions of fields will still not match)-- is this doable then?

6
  • 3
    I'm sure the compiler didn't like it. It's pretty far from valid C syntax. Commented May 31, 2017 at 17:59
  • @JohnBollinger Is this doable in C though? What if the data types are of the same size? Commented May 31, 2017 at 18:03
  • Whatever you are trying to do: get it working properly with one data type first. Please make your mind up: same size or different size? Commented May 31, 2017 at 18:04
  • 1
    xyproblem.info What are you trying to achieve? Commented May 31, 2017 at 18:07
  • The variability in the bit field size prevented me from trying a union. Uh... What? The rule is that a union is large enough to hold its largest member, at all times, i.e. regardless of which member is currently active. There is no "variability". Commented May 31, 2017 at 18:16

1 Answer 1

2

Inside the function, you can convert ptr to type char * or int *, or to a pointer to a struct or union type, but every pointer points to exactly one type. Such a conversion produces undefined behavior if the result would fail to be appropriately aligned for the pointer type, but that will not happen when casting to a type of object that ptr actually does point to.

Furthermore, you can freely access the bytes of any object's representation via a pointer of character type (char *, unsigned char *, etc.). If you attempt to access an object via a pointer to an object of a different, incompatible type, however, then you produce undefined behavior. Accessing the pointed-to object is a separate consideration from converting the pointer to a different pointer type.

Thus, you can do this:

void function(int index, void *ptr) {
    // treat `ptr` as pointing to the first element of an array of int
    int *pointer = ptr;
    pointer[index]++;  // UB here if ptr really points to something other than int
}

and this:

void function(int index, void *ptr) {
    // treat `ptr` as pointing to the first element of an array of char
    char *pointer = ptr;
    pointer[index]++;
}

and even this:

void function(int index, void *ptr, _Bool is_int_ptr) {
    // Treat ptr as pointing to char or int depending on the value of is_int_ptr
    if (is_int_ptr) {
        int *pointer = ptr;
        pointer[index]++;
    } else {
        char *pointer = ptr;
        pointer[index]++;
    }
}

But the pointer value itself does not carry information about which type it points to. You need a mechanism to tell the program which type it points to. Ordinarily, that would be via the function parameter's declared type (making the function specific to that type), but you can convey it via a separate parameter, as in the last example.

Sign up to request clarification or add additional context in comments.

3 Comments

Probably the better thing to do at this point would be, to have an array of functions, and the function to be called would be determined by the index of the array. Thanks!
Also, conversion to int * is undefined already without dereference if the original pointer is not suitably aligned...
Thanks, @AnttiHaapala, I have updated the answer to mention that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.