Thread: Implementing custom behaviour in C but something fails

  1. #1
    Registered User
    Join Date
    Sep 2014
    Posts
    121

    Implementing custom behaviour in C but something fails

    Hello, I am creating a special struct with unknown functions. I use this approach:
    Callbacks.h
    Code:
    #ifndef CALLBACKS
    #define CALLBACKS
    struct Callbacks;
    
    struct Callbacks* getNewCallback();
    
    #endif // CALLBACKS
    And implementing it that way:
    Code:
    #include "callbacks.h"
    #include <stdlib.h>
    #include <stdio.h>
    typedef void (*doit)(void);
    typedef void (*dont)(void);
    struct Callbacks {
        doit doers[1];
        dont donters[1];
    };
    
    static inline void __do1(void) {
        printf("Do it 1\n");
    }
    static inline void __do2(void) {
        printf("Do it 2\n");
    }
    static inline void __do3(void) {
        printf("Do it 3\n");
    }
    static inline void __do4(void) {
        printf("Do it 4\n");
    }
    
    static inline void __dont1(void) {
        printf("Don`t 1\n");
    }
    static inline void __dont2(void) {
        printf("Don`t 2\n");
    }
    static inline void __dont3(void) {
        printf("Don`t 3\n");
    }
    static inline void __dont4(void) {
        printf("Don`t 4\n");
    }
    
    
    
    struct Callbacks* getNewCallback() {
        struct Callbacks {
            doit doer[4];
            dont donters[4];
        };
        int i=0;
    
        struct Callbacks* cb = (struct Callbacks*) malloc(
                    sizeof(struct Callbacks));
        cb->doer[0]= __do1;
        cb->doer[1]= __do2;
        cb->doer[2]= __do3;
        cb->doer[3]= __do4;
    
        cb->donters[0] = __dont1;
        cb->donters[1] = __dont2;
        cb->donters[2] = __dont3;
        cb->donters[3] = __dont4;
    
        return cb;
    }
    
    
    int main(int argc, char** argv) {
        struct Callbacks* cb = getNewCallback();
        int i=0;
        while ( i < 4 ) {
            cb->doers[i]();
            i++;
        }
        i=0;
        while ( i < 4 ) {
            cb->donters[i]();
            i++;
        }
    }
    When I ran it only the calls from doers array is called 7 times normally, and donters only one time. Why is that? When I call doers from the second loop, it prints the doers functions again....and only one call to donters is made to the first static inline donter functions __dont1()...
    Last edited by heatblazer; 01-02-2015 at 12:39 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    So is some part of this warning confusing you?
    Code:
    $ gcc -Wall bar.c
    bar.c: In function ‘getNewCallback’:
    bar.c:58:5: warning: return from incompatible pointer type [enabled by default]
    bar.c:44:9: warning: unused variable ‘i’ [-Wunused-variable]
    bar.c: In function ‘main’:
    bar.c:74:1: warning: control reaches end of non-void function [-Wreturn-type]
    $ ./a.out 
    Do it 1
    Do it 2
    Do it 3
    Do it 4
    Do it 2
    Do it 3
    Do it 4
    Don`t 1
    As far as the outer struct is concerned, the dont array begins where the inner struct has do[1]
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    I`ve fixed that, thanks.
    Code:
    struct Callbacks* getNewCallback() {
        struct Callbacks {
            dont* donters;
            doit* doer;
        };
        int i=0;
    
        struct Callbacks* cb = (struct Callbacks*) malloc(
                    sizeof(struct Callbacks));
        cb->doer = (doit*)malloc(sizeof(doit)*4);
        cb->doer[0] = __do1;
        cb->doer[1] = __do2;
        cb->doer[2] = __do3;
        cb->doer[3] = __do4;
    
        cb->donters = (dont*)malloc(sizeof(dont)*4);
        cb->donters[0] = __dont1;
        cb->donters[1] = __dont2;
        cb->donters[2] = __dont3;
        cb->donters[3] = __dont4;
    
        return cb;
    }
    I just dynamically alloc everything.

  4. #4
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    I`ve also changed the Callbacks struct to have pointers instead 1 size array:
    Code:
    struct Callbacks {
        dont* donters;
        doit* doers;
    
    };

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Perhaps
    Code:
    struct Callbacks {
        int numDonts;
        dont* donters;
        int numDos;
        doit* doers;
    };
    Then you don't have to keep messing about redeclaring your structure, and anything which might use the struct has all the info it needs.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    Quote Originally Posted by Salem View Post
    Perhaps
    Code:
    struct Callbacks {
        int numDonts;
        dont* donters;
        int numDos;
        doit* doers;
    };
    Then you don't have to keep messing about redeclaring your structure, and anything which might use the struct has all the info it needs.
    Yes you are right. My idea actually was to add some privacy called from a function, to have some kind of different structs called form different functions, but aparently the compiler can`t tell what is in the local variables of the function. I expecting that using an opaque pointer will give the compiler a less care about what exactly Callbacks is, it can have 1 integer or 20 different items, however it is really impossible for the compiler to tell what a local function will create and will return. Makes sense. My idea is to imeplement different behaviour per object with this Callabacks struct, it works now. Thanks for hinting me

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Using identifiers with leading underscores is a really bad idea, as they are often reserved for use by the implementation (compiler and library). If you get a clash, the results are undefined.

    More info in the C FAQ, here.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    Quote Originally Posted by grumpy View Post
    Using identifiers with leading underscores is a really bad idea, as they are often reserved for use by the implementation (compiler and library). If you get a clash, the results are undefined.

    More info in the C FAQ, here.
    Thanks, I`ll keep that in mind. I just assumed that no one would use such names

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Custom exceptions with default behaviour
    By Neo1 in forum C++ Programming
    Replies: 8
    Last Post: 05-25-2013, 11:09 PM
  2. Why this fails?
    By manav in forum C++ Programming
    Replies: 13
    Last Post: 05-29-2008, 01:11 PM
  3. trying to rea from /dev/tty fails!
    By arunj in forum Linux Programming
    Replies: 4
    Last Post: 10-17-2007, 03:59 AM
  4. realloc fails
    By beginner.c in forum C Programming
    Replies: 12
    Last Post: 04-27-2007, 08:42 AM
  5. Replies: 0
    Last Post: 04-06-2007, 04:55 PM