By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,159 Members | 992 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,159 IT Pros & Developers. It's quick & easy.

Constructor equivalent

P: n/a

Hi,

since C does not support construcor functions for structs, what is the
usual approach to write this C++ code in C:
Expand|Select|Wrap|Line Numbers
  1. struct foo
  2. {
  3. foo() {bar=0;}
  4. int bar;
  5. };
  6.  
  7. int main()
  8. {
  9. foo f[5];
  10. }
  11.  
I would write:
Expand|Select|Wrap|Line Numbers
  1. struct foo
  2. {
  3. bar;
  4. };
  5.  
  6. Init(foo& f)
  7. {
  8. bar=0;
  9. }
  10.  
  11. int main(int, char**)
  12. {
  13. foo f[5];
  14. // Put this in a Macro: INIT(f)?
  15. for(int i=0; i<sizeof(f)/sizeof(f[0]); ++i)
  16. Init(f[i]);
  17. return 0;
  18. }
  19.  
Any better ideas?

--
-Gernot
int main(int argc, char** argv) {printf
("%silto%c%cf%cgl%ssic%ccom%c", "ma", 58, 'g', 64, "ba", 46, 10);}

Jun 27 '06 #1
Share this Question
Share on Google+
14 Replies


P: n/a

Gernot Frisch wrote:
Hi,

since C does not support construcor functions for structs, what is the
usual approach to write this C++ code in C:
Expand|Select|Wrap|Line Numbers
  1.  struct foo
  2.  {
  3.      foo() {bar=0;}
  4.      int bar;
  5.  };
  6.  int main()
  7.  {
  8.      foo f[5];
  9.  }
  10.  

I would write:
Expand|Select|Wrap|Line Numbers
  1.  struct foo
  2.  {
  3.      bar;
  •  
  • Her, I'd prefer
  •  
  • int bar;
  •  
  • It's always good to spell things out.
  •  };
  •  Init(foo& f)
  •  
  • void Init(foo *f)
  •  
  • Omitting function type defaults to `int` (which pre-C99 would require a
  • `return`).
  •  {
  •      bar=0;
  •  
  • Here, `bar` is unknown. Since it's a member of your struct, you'll
  • need:
  •  
  • f->bar = 0;
  •  }
  •  int main(int, char**)
  •  
  • int main(int argc, char **argv)
  •  
  • You need this here, as it's definition, not just declaration.
  • Otherwise, how do you expect to refer to the two parameters below (it
  • doesn't matter that you actually don't).
  •  {
  •      foo f[5];
  •      // Put this in a Macro: INIT(f)?
  •  
  • I wouldn't. I also wouldn't use C99 comments, especially on Usenet.
  •      for(int i=0; i<sizeof(f)/sizeof(f[0]); ++i)
  •  
  • I'd also declare `i` outside of `for`, but that may be a matter of
  • taste.
  •         Init(f[i]);
  •  return 0;
  •  }
  •  

  • Any better ideas?

    Yours seems to be OK, apart from apparent inexperience in C.

    Jun 27 '06 #2

    P: n/a
    Any better ideas?


    Yours seems to be OK, apart from apparent inexperience in C.


    I just woosh-woosh-typed that thing so you could get my point. Thank
    you for the clearing, though.
    Jun 27 '06 #3

    P: n/a

    Gernot Frisch wrote:
    Any better ideas?


    Yours seems to be OK, apart from apparent inexperience in C.


    I just woosh-woosh-typed that thing so you could get my point. Thank
    you for the clearing, though.


    I guessed as much, hence "apparent". It saves everybody's time if you
    try to post as correct code as possible (i.e. no silly woosh-woosh
    errors ;-) ). As you probably know, in c.l.c even the smallest of
    things get corrected (a Good Thing).

    Jun 27 '06 #4

    P: n/a
    Gernot Frisch wrote:
    Hi,

    since C does not support construcor functions for structs, what is the
    usual approach to write this C++ code in C: .... int main(int, char**)
    {
    foo f[5];
    // Put this in a Macro: INIT(f)?
    for(int i=0; i<sizeof(f)/sizeof(f[0]); ++i)
    Init(f[i]);
    return 0;
    }
    [/code]

    Any better ideas?


    Typically, I would have a module foo.c. It would declare
    struct foo;
    FooInit(struct *foo foop);
    FooGroom (struct *foo foop, int bar);
    etc.

    --
    Thad
    Jun 27 '06 #5

    P: n/a
    "Gernot Frisch" wrote:
    since C does not support construcor functions for structs, what is the
    usual approach to write this C++ code in C:
    Expand|Select|Wrap|Line Numbers
    1. struct foo
    2. {
    3.     foo() {bar=0;}
    4.     int bar;
    5. };
    6. int main()
    7. {
    8.     foo f[5];
    9. }

    I would write:
    Expand|Select|Wrap|Line Numbers
    1. struct foo
    2. {
    3.     bar;
    4. };
    5. Init(foo& f)
    6. {
    7.     bar=0;
    8. }
    9. int main(int, char**)
    10. {
    11.     foo f[5];
    12.     // Put this in a Macro: INIT(f)?
    13.     for(int i=0; i<sizeof(f)/sizeof(f[0]); ++i)
    14.        Init(f[i]);
    15. return 0;
    16. }

    Any better ideas?


    Yes. Do you own "C with classes" as C-front did. Include methods in
    the structure as function pointers, with an explicit parameter for the
    struct itself. (Replacing "this".)

    struct foo
    {
    int bar;
    void (*init)(struct foo* this);
    };

    int main()
    {
    struct foo f;
    ...
    f.init(&f);
    }

    Similar code from a real project:

    ( Notes: was(Un)formatted to fit here, will not compile as-is, several
    typedefs and definitions missing.)

    ============================

    //--------------------------------------------------------------
    // message descriptor structure
    //--------------------------------------------------------------

    typedef struct msg_desc msg_desc_s;

    struct msg_desc
    {
    msg_type_e type; // <- Message type (id for
    // internal system transfers).
    uint16_t code; // <- Message code (id for on-the
    // -wire transfers).
    uint16_t code_mask;// <- Bit mask to extract code.
    char *name; // <- Message name. For debugging
    // only, can be removed if we
    // run short of memory.
    bool (*init)(msg_desc_s const * const desc);
    // ^- Initialization function.
    bool (*encode)(prv_msg_s * prv_msg,
    const ccs_msg_s * app_msg);
    // ^- Message encoding function.
    bool (*decode)(ccs_msg_s * app_msg,
    const prv_msg_s * prv_msg);
    // ^- Message decoding function.
    bool (*time_update)(isr_msg_s * isr_msg);
    // ^- Time update function. Called
    // by the transmit ISR immediately
    // before delivering a message to
    // the FPGA. NULL for
    // messages that do not carry
    // timing information
    bool (*insert)(prv_msg_s * fifo,
    const prv_msg_s * prv_msg);
    // ^- Function to insert message
    // in transmit fifo.
    // Normally points to fifo_insert(),
    // but can be replaced to implement
    // message type specific fifo
    // bumping/replacement policies.
    uint16_t leng; // <- Message length.
    uint16_t repeat; // <- Number of time message should be
    // repeated.
    uint16_t flags; // <- Message flags. //%TODO% - define,
    // remove?
    bool keep; // <- If true do not remove from
    // fifo after transmission (for
    // messages that need
    // acknowledgement, etc.)
    prv_msg_s *fifo; // <- Pointer to per type message
    // transmit fifo.
    uint16_t fifo_size;// <- Fifo size. Today all fifos
    // are of size COM_TX_FIFO_SIZE.
    // This is a place holder to
    // allow per-message-type fifo
    // sizes in the future.
    uint16_t ttl; // <- Message time to live. If a
    // message remains in a transmit
    // fifo longer than this time,
    // (most likely because of higher
    // priority messages being
    // transmitted ahead of it,) it
    // will be deleted.
    bool can_abort;// <- If true, message transmition
    // can be aborted when higher
    // priority messages are pending.
    // Valid only for messages of
    // leng > 1 - (*NOT* used yet)
    uint16_t rx_mbx; // <- Receive mailbox index
    uint16_t msg_delay;// <- Minimum intermessage delay
    bool (*tx_process)(const prv_msg_s * prv_msg);
    // ^- Called before transmision for
    // message-specific post-processing.
    // NULL if not needed
    bool (*rx_process)(ccs_msg_s * app_msg,
    const prv_msg_s * prv_msg);
    // ^- Called after receiving for
    // message-specific post-processing
    // NULL if not needed
    msg_stats_s *stats; // <- Per-message statistics block
    };

    ============================

    Sample usage:
    msg_desc_s *desc = ...;
    bool stat;

    ....
    // encode message
    stat = (desc->encode)(com1_tx_prv_msg, com1_tx_app_msg);

    // encoding errors ?
    if (!stat)
    {
    // yes, update error counters & exit
    desc->stats->txtsk_encode_errors++;
    continue;
    }

    // call post-process function if neccessary
    if (desc->tx_process)
    {
    stat = (desc->tx_process)(com1_tx_prv_msg);
    // post-process errors?
    if (!stat)
    {
    // yes, update error counters and exit
    // without updating transmit fifos
    desc->stats->txtsk_process_errors++;
    continue;
    }
    }

    // insert in fifo for transmission
    stat = (desc->insert)(desc->fifo, com1_tx_prv_msg);

    // insertion failed ?
    if (!stat)
    {
    // yes, update error counters & exit
    desc->stats->txtsk_fifo_insert_errors++;
    continue;
    }

    ....
    Jun 27 '06 #6

    P: n/a
    Any better ideas?


    Yes. Do you own "C with classes" as C-front did. Include methods in
    the structure as function pointers, with an explicit parameter for
    the
    struct itself. (Replacing "this".)

    struct foo
    {
    int bar;
    void (*init)(struct foo* this);
    };

    int main()
    {
    struct foo f;
    ...
    f.init(&f);
    }


    For programming a microcontroller: Every struct's sizeof() would be
    sizeof(members) + sizeof(method_pointers), right? So, this might be
    inefficient for a device with 1K RAM, no? (not cynical - this is a
    true question)
    Jun 28 '06 #7

    P: n/a
    Gernot Frisch wrote:
    Any better ideas?


    Yes. Do you own "C with classes" as C-front did. Include methods in
    the structure as function pointers, with an explicit parameter for
    the
    struct itself. (Replacing "this".)

    struct foo
    {
    int bar;
    void (*init)(struct foo* this);
    };

    int main()
    {
    struct foo f;
    ...
    f.init(&f);
    }

    For programming a microcontroller: Every struct's sizeof() would be
    sizeof(members) + sizeof(method_pointers), right? So, this might be
    inefficient for a device with 1K RAM, no? (not cynical - this is a
    true question)

    Correct.

    --
    Ian Collins.
    Jun 28 '06 #8

    P: n/a
    Ian Collins wrote:

    Gernot Frisch wrote:
    Any better ideas?

    Yes. Do you own "C with classes" as C-front did. Include methods in
    the structure as function pointers,
    with an explicit parameter for the
    struct itself. (Replacing "this".)

    struct foo
    {
    int bar;
    void (*init)(struct foo* this);
    };

    int main()
    {
    struct foo f;
    ...
    f.init(&f);
    }

    For programming a microcontroller: Every struct's sizeof() would be
    sizeof(members) + sizeof(method_pointers), right? So, this might be
    inefficient for a device with 1K RAM, no? (not cynical - this is a
    true question)

    Correct.


    What are you talking about?
    The size of a struct is the size of the members
    plus the padding bytes.

    For the code shown above,
    bar is one member of the struct, init is the other.

    --
    pete
    Jun 28 '06 #9

    P: n/a
    "Gernot Frisch" wrote:
    ...
    For programming a microcontroller: Every struct's sizeof() would be
    sizeof(members) + sizeof(method_pointers), right? So, this might be
    inefficient for a device with 1K RAM, no? (not cynical - this is a
    true question)


    I understand your question, but the wording is incorrect. The size of
    the structure is sizeof(the_structure).
    Yes, it is going to be larger if pointer to method functions are
    included per my suggestion.
    And yes, it is not a good suggestion is memory size is critical.
    Jun 28 '06 #10

    P: n/a
    pete wrote:
    Ian Collins wrote:
    Gernot Frisch wrote:
    >Any better ideas?

    Yes. Do you own "C with classes" as C-front did. Include methods in
    the structure as function pointers,
    with an explicit parameter for the
    struct itself. (Replacing "this".)

    struct foo
    {
    int bar;
    void (*init)(struct foo* this);
    };

    int main()
    {
    struct foo f;
    ...
    f.init(&f);
    }
    For programming a microcontroller: Every struct's sizeof() would be
    sizeof(members) + sizeof(method_pointers), right? So, this might be
    inefficient for a device with 1K RAM, no? (not cynical - this is a
    true question)


    Correct.

    What are you talking about?
    The size of a struct is the size of the members
    plus the padding bytes.

    For the code shown above,
    bar is one member of the struct, init is the other.

    The OP was differentiating between data members and function pointer
    members. I thought that was quite clear from the way he phrased his
    question.

    --
    Ian Collins.
    Jun 28 '06 #11

    P: n/a
    Gernot Frisch wrote:
    struct foo
    {
    int bar;
    void (*init)(struct foo* this);
    };


    For programming a microcontroller: Every struct's sizeof() would be
    sizeof(members) + sizeof(method_pointers), right? So, this might be
    inefficient for a device with 1K RAM, no? (not cynical - this is a
    true question)


    Right, this would be an ok way to do virtual functions, for instance,
    but the facility with an init function isn't really useful since you
    need to know how to init the thing before the pointer will be set in
    the first place!

    E.g. it is not entirely valid to do:

    int main(void)
    {
    foo f;
    f.init(&f);
    }

    ....since f hasn't been initialized in any way, and init doesn't point
    at anything defined.

    -tom!
    Jun 28 '06 #12

    P: n/a
    Ian Collins <ia******@hotmail.com> writes:
    [...]
    The OP was differentiating between data members and function pointer
    members. I thought that was quite clear from the way he phrased his
    question.


    Sure, but C makes no such distinction; function pointer members are
    data members. (I understand that C++ introduces some more complexity
    in this area, with some members possibly being implicit.)

    --
    Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Jun 28 '06 #13

    P: n/a
    Keith Thompson wrote:
    Ian Collins <ia******@hotmail.com> writes:
    [...]
    The OP was differentiating between data members and function pointer
    members. I thought that was quite clear from the way he phrased his
    question.

    Sure, but C makes no such distinction; function pointer members are
    data members. (I understand that C++ introduces some more complexity
    in this area, with some members possibly being implicit.)

    That was probably the clarification he required, doing "C with classes"
    has a cost in the form of the function pointer members of the struct.
    This isn't the case in C++, so this cost is something someone form a C++
    background might overlook.

    Cheers,

    --
    Ian Collins.
    Jun 28 '06 #14

    P: n/a

    int main(void)
    {
    foo f;
    f.init(&f);
    }

    ...since f hasn't been initialized in any way, and init doesn't
    point
    at anything defined.


    Right. So I need an pre-initializer as well. My question was just
    about the c'tor for an array of structs, so I see, there's not other
    way then just looping through each element and initialize it with a
    function.

    Thank you all. I though so, but I wanted to not overlook something.
    Jun 29 '06 #15

    This discussion thread is closed

    Replies have been disabled for this discussion.