Question

This is unfortunately defined in some external library: cannot touch!

// library.h
typedef struct {
    long foo;
    char *bar;
   /* ... (long & complex stuff omitted) */
} *pointer_to_complex_struct_t;

Now The Question: how to declare an complex_struct_t variable?

  • Ideal solution but not allowed! (cannot change external library):

    // library.h
      /* ... (long & complex stuff omitted) */
    } complex_struct_t, *pointer_to_complex_struct_t;
    
    
    // my.h
    extern complex_struct_t my_variable;
    
  • Non-portable solution (gcc):

    // my.h
    extern typeof( * (type_placeholder)0 )  my_variable; // Thanks caf!
    
  • Other? Better? Thanks!

Bonus question: same question for a function pointer (in case there is any difference; I doubt it).


ADDED bonus: below is the exact same question but with functions instead of structs. This should not make any difference to the short answer ("No."), the only answer I was initially interested in. I did not expect some people to die trying to know and get my job done with creative workarounds, which is why I simplified the question from functions to structs (function pointers have special implicit conversion rules for convenience and confusion). But hey, why not? Let's get the copy-paste workaround competition started. Some workarounds are probably better than others.

///// library.h //////
// Signature has been simplified
typedef double (*ptr_to_callback_t)(long, int, char *);
// Too bad this is not provided: typedef double callback_t(long, int, char *);

///// my.h /////
// This avoids copy-paste but is not portable
typedef typeof( * (ptr_to_callback_t)0 ) callback_t;

extern callback_t callback_1;
extern callback_t callback_2;
extern callback_t callback_3;
// etc.

Short answer = no, there is currently no portable alternative to typeof

A basic copy-paste workaround works OK for functions but not for structs. The compiler will match the duplicated function types, but will not relate the duplicated struct types: a cast is required and the duplicated struct types will diverge without compilation warning.

Was it helpful?

Solution

No, unfortunately you cannot do it with standard C. With C++ a simple metafunction would do the trick though.

However you could just copy-paste the definition of the struct thus leaving the original untouched

typedef struct {
 ///same  struct
} complex_struct_t;

The downside of this solution is that the expression &complex_struct_t won't be of type pointer_to_complex_struct_t, instead it will be of type pointer to unnamed struct {//your members}; You'll need reinterpret_casting, if you need that feature...

OTHER TIPS

As written, the answer to your question is "no"; if all you have is a type definition of

typedef struct {...} *ptr_to_struct;

then there's no (standard, portable) way to extract the struct type. If you have to create an instance of the struct, the best you will be able to do is

ptr_to_struct s = malloc(sizeof *s);

and then refer to the fields in the struct using the -> component selection operator (or by dereferencing s and using the . operator, but you don't want to do that).

You asked if the same thing applied to function pointers; you really need to state exactly what you mean. If you have a situation like

typedef struct {...} *ptr_to_struct;
ptr_to_struct foo() {...}

then the situation is exactly like the above; you don't have a way to declare a variable of that type.

Make a local copy of the header file and include it instead of the original. Now you can do anything you want. If this library could change (update or anything else), you could write a little script to automate these steps and call it from your makefile whenever you compile. Just make sure to not blindly paste into the header, search for the specific line (} *pointer_to_complex_struct_t;) and throw an error if it is no longer found.

Maybe you have to be a bit careful with the search paths for includes if this header uses other headers of this library. Plus, with the order of includes if itself is included by other headers.

EDIT (for your real goal mentioned in a comment): You can't do this with function pointers. Just write the function you want with the signature of the typedef, and it will be compatible to the pointer and can be called by it.

How about:

pointer_to_complex_struct_t newStruct ( void ) {
    pointer_to_complex_struct_t ptr = 
         (pointer_to_complex_struct_t) malloc ( sizeof (*pointer_to_complex_struct_t) );
    return ptr;
}

You'd have to reference your newly created struct through ptr-> but you could create new ones.

Of course, this may or may not work, depending on how the struct is actually used. The example that comes to mind is: what if the struct ends with

char data[0];

and data is used to point into the memory following the structure.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top