简体   繁体   中英

C cast syntax, how about complex casts?

I need some help in C syntax, more about C casting syntax.
All information I found in web is about simple casts like (int) or (char) etc...
I always get stuck in casting void* to a array or multi-dimentisional array or pointers of such things, but I never know how to do that! All that I do in these cases was trying things like (char []) or (char *[]) or (*char []) without any idea what I'm doing, until I get no errors about type casting.

Anybody have a thumb of rule to follow or some tips or tricks to do that?
For example I have a arry of void pointers and I pass it to a function, how to turn it into array again?

main () {
   int data1, data2;
   char data3, data4;
   void *function_data[] = {data1, data2, data3, data4};
   some_function (function_data);
   return;
}


some_function (void *data) {
   void *function_d[4];
   function_d = (void *[]) data; //It not work, how to cast data?
}

EDIT: I wrote wrong, I thinked that it wasn't important, so, I changed the variables data* of my code for better undestand.

Your problem is that void *function_d[4]; creates new array. You cannot assign other array to it. function_d should be of type void** .

The basic idea is to use the type definition of the intended type without the variable name and placed in parentheses as a cast to that type. For example:

int c;
c = (int) 4;

and

char * (*functionptr)(float, double);
functionptr = (char * (*)(float, double))myfunction;

Of course always assuming the type cast is possible and makes sense. Be aware: C doesn't prevent most nonsensical casts, so you'll have to take care yourself.

In your case, function_data is defined to be an array of pointers to void. Therefore, each data needs to be of type void ** , as Keith already indicated. By calling some_function with function_data as parameter, you're passing a pointer to function_data[0] into the function. In order for your function to use it again as an array of 4 pointers to void, you would need to use a cast like you did, (void*[]). However, the array function_d is an array reserving also the space for four pointers, and you cannot change the function_d pointer (it is of type void * * const !). To do what you seem to want, you'll need a non-const pointer, like

void * * function_d = (void*[])data;

You may then still use it in the same way like function_data , using subscription like an array. function_d[2] will give you the value equal to *data3 .

You cannot assign to an array object.

How are data1 , data2 , data3 , and data4 declared?

void* is (or can be used as) a generic pointer type. That can give you tremendous flexibility, but it can also inhibit type checking.

function_data is an array of 4 pointers to void. In the call some_function (function_data) , it's implicitly converted to void** , a pointer to the first element.

some_function expects a void* , not a void** -- but any pointer type (other than a function pointer) can be implicitly converted to void* , so the compiler doesn't complain about the call.

Here's a version of your program that's at least type-correct (I think).

#include <stddef.h>

void some_function(void **data, size_t count);

int main(void) {
    void **data1, **data2, **data3, **data4;
    void *function_data[] = { *data1, *data2, *data3, *data4 };
    some_function (function_data,
                   sizeof function_data / sizeof function_data[0]);
    return 0;
}

void some_function(void **data, size_t count) {
    size_t i;
    for (i = 0; i < count; i ++) {
        /*
         * do something with data[i], which is of type void*
         */
    }
}

Note that data1 and friends are not initialized, so this program's behavior is undefined. I suspect you meant to write something like:

void *function_data[] = { &data1, &data2, &data3, &data4 };

but it's hard to tell just what you're trying to do.

If you really need the function to have a copy of the array, you can use memcpy() (you can't assign array values). For most purposes, though, it makes more sense to use pointers to access the original array. You'll need to make a copy if you want to modify the copy without affecting the original.

And I've corrected the declarations for main and some_function , and added a declartion for some_function to the top so it's visible when you call it.

You should always explicitly declare the return type for all your functions. In the 1990 version of C, you can omit it, and it will default to int (but it's still better to declare it as int explicitly). In the 1999 version of C, the type is required, and you can't call a function without a visible declaration.

Again, it's hard to tell from the code you've shown us just what you're trying to do, which makes it difficult to guess how to do it.

Several issues:

This isn't going to work:

int data1, data2;
char data3, data4;
void *function_data[] = {data1, data2, data3, data4};

because int and char are not compatible with void * . You could fix this as follows:

void *function_data[] = {&data1, &data2, &data3, &data4};

because int * and char * are compatible with void * .

When you pass function_data to some_function , the array expression is converted to a pointer value, so what some_function receives is a void ** . You can use the subscript operator on the pointer as though it were an array:

some_function(function_data);
...
void some_function(void **data)
{
  int *x = data[0];  // remember, we stored the *addresses*
  int *y = data[1];  // of data1, data2, data3, and data4;
  char *a = data[2]; // since the type of data is void **,
  char *b = data[3]; // the type of data[i] is void *.
  ...
}

IOW, you don't need to cast data to an array type in order to use it like an array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM