Thread: Multi-struct function?

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    58

    Multi-struct function?

    Hi

    I have a number of different strut composite variables and a single function that I want to pass them to, is it possible through casting or another method to be able to pass these different struts to a single method?

    Code:
    Struct A {
        uint8_t data1;
        uint16_t data2;
        uint8_t data3;
    } // structa
    
    Struct B {
        uint32_t data1;
        uint16_t data2;
        uint8_t data3;
        uint16_t data4;
        uint16_t data5;
        uint8_t data5;
    } // structb {
    
    Struct C {
        uint16_t data1;
        uint16_t data2;
    } // structc
    
    Function1(StructA);
    Function1(StructB);
    Function1(StructC);
    
    Void Function1(uint8_t anyStruct) {
    
        For (i=0; I < sizeof(anyStruct); i++) {
            // print each byte onto the console for example usage
        } // for
    
    } // function 1
    Many thanks :-)

    David

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You could pass a pointer to anything as a void *; however, the function itself would have no way of knowing which struct got passed in or how to deal with it in any meaningful way.

  3. #3
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    You can use a void pointer to pass a pointer to anything in.

    Maybe you could use sizeof to get the size of the stuct within the function and print out each byte. Not sure if it would work as i have never tried it.

  4. #4
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    oh right, how would that look in code then? Something like this?

    Code:
    Function1(StructA);
    Function1(StructB);
    Function1(StructC);
    
    Void Function1(void* anyStruct) {
    
        For (i=0; I < sizeof(anyStruct); i++) {
            // print each byte onto the console for example usage
        } // for
    
    } // function 1

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Well, no.

    sizeof(anyStruct) == sizeof(void *) == 4 (probably).
    sizeof(void) is not defined.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    In C, a function normally takes only one type of argument(s). You can make any pointer match a void *, so passing the address of your struct would work. sizeof() on a pointer, however, would not give you the right value.


    You have two options, either:
    * pass along which type of struct you actually passed in (you probably need to know which struct it is anyways) - and then determine the size using something like "if (type == 'A') size = sizeof(struct A);",
    * Pass in the size of the struct itself.

    Of course, there are other variants on the theme: You could put a common struct at the beginning of all structs, which contains one of or both the size and type of struct.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    oh sorry, I was talking about actually passing the struct to the function, not the size of part :-)

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by DavidDobson View Post
    oh sorry, I was talking about actually passing the struct to the function, not the size of part :-)
    Yes, but using sizeof() on something that has been passed to a function, where "something" is a pointer to one of several different structures will not work - because your code will not know what the pointer is pointing to.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    oh ic, I don't actually want to use size of at all, it was just for the example of what I want to do with the function What I need to do is pass any type of struct to a single function.

    thanks

    David

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    You could also pass a union as an argument, although that's sort of like what mats suggested earlier. Your function is defined by cases.

    Code:
    struct A;
    struct B;
    
    union OneOfThese
    {
      struct A init_a;
      struct B init_b;
    };
    
    void foo (union OneOfThese * item, int option)
    {
      switch (option) {
        case 'a':
          /* union is a A */
        break;
        case 'b':
          /* union is a B */
        break;
        default:
          /* bad arguments */
      }
    }
    Or something like that anyway.

  11. #11
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Switch to c++ and this becomes easy.

    But the problem is one method can't do something with three different data formats. It would have to convert whatever data it needs into a standard format before using it. Or it would have to have a big switch statement for each type, in which case there is no point of having it be one method.

    Your best option is to have several separate similarly named functions that convert the data to a common format to be used by the common function. If it is not possible to derive a common function that deals with the relevant data, but the structure of the code is the same for all variants, then you can use a macro for the common function, still keeping the struct specific functions to enforce type safety.

    EDIT, for example the function above:
    Code:
    void function1A(StructA);
    void function1B(StructB);
    void function1C(StructC);
    void function1_impliment(int size, char *data);
    
    void function1A(StructA *struct){
       function1_impliment(sizeof(StructA), (char*)struct);
    }
    
    void function1B(StructB *struct){
       function1_impliment(sizeof(StructB), (char*)struct);
    }
    
    
    void function1C(StructC){
       function1_impliment(sizeof(StructC), (char*)struct);
    }
    
    
    void function1_impliment(int size, char *data){
        for (i=0; I < sizeof(anyStruct); i++) {
            putchar();
        } 
    }
    Also to avoid code repletion you can use a macro like this:
    Code:
    #define function1_body(type) \
    void function1##type(type*struct){
       function1_impliment(sizeof(type), (char*)struct);
    }
    But you still need to call a different function for each type because C does not support overloading.

    EDIT 2: I just realized that I am basically showing you how to implement templates in C. In C++ templates are much more common, though admittedly the code isn't much prettier.
    Last edited by King Mir; 10-10-2008 at 10:38 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  12. #12
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    In C++ you could do this an entirely different way...

    Why not just do as many sub-systems of the Win32 API do?

    Example:
    Code:
    struct myImage
    {
      int size;
      int height, width;
      char pixels[];
    };
    
    struct mySprite
    {
      int size;
      int imageId, x, y;
    }
    
    void doStuff(void *p)
    {
      switch(*(int *)p)
      {
        case sizeof(myImage):
          ...
        case sizeof(mySprite):
          ...
      }
    }
    Where the size parameter is always set to size of the structure.

    Just a thought...

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Or more likely, in C++, you would use member functions and perhaps inheritance to solve the problem.

    And that is of course a possible solution in C too - just use a common structure with function pointers that is at the beginning of all of the other structures, and call a function that does the right thing(s).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Quote Originally Posted by King Mir View Post
    Code:
    void function1A(StructA *struct){
       function1_impliment(sizeof(StructA), (char*)struct);
    void function1B(StructB *struct){
       function1_impliment(sizeof(StructB), (char*)struct);
    void function1C(StructC){
       function1_impliment(sizeof(StructC), (char*)struct);
    void function1##type(type*struct){
       function1_impliment(sizeof(type), (char*)struct);
    struct is a keyword.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Link List math
    By t014y in forum C Programming
    Replies: 17
    Last Post: 02-20-2009, 06:55 PM
  2. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  3. Replies: 10
    Last Post: 05-18-2006, 11:23 PM
  4. towers of hanoi problem
    By aik_21 in forum C Programming
    Replies: 1
    Last Post: 10-02-2004, 01:34 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM