Constructor equivalent

G

Gernot Frisch

Hi,

since C does not support construcor functions for structs, what is the
usual approach to write this C++ code in C:
Code:
struct foo
{
    foo() {bar=0;}
    int bar;
};

int main()
{
    foo f[5];
}

I would write:
Code:
struct foo
{
    bar;
};

Init(foo& f)
{
    bar=0;
}

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;
}

Any better ideas?
 
V

Vladimir Oka

Gernot said:
Hi,

since C does not support construcor functions for structs, what is the
usual approach to write this C++ code in C:
Code:
struct foo
{
foo() {bar=0;}
int bar;
};

int main()
{
foo f[5];
}

I would write:
Code:
struct foo
{
bar;[/QUOTE]

Her, I'd prefer

  int bar;

It's always good to spell things out.
[QUOTE]
};

Init(foo& f)[/QUOTE]

  void Init(foo *f)

Omitting function type defaults to `int` (which pre-C99 would require a
`return`).
[QUOTE]
{
bar=0;[/QUOTE]

  Here, `bar` is unknown. Since it's a member of your struct, you'll
need:

      f->bar = 0;
[QUOTE]
}

int main(int, char**)[/QUOTE]

  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).
[QUOTE]
{
foo f[5];
// Put this in a Macro: INIT(f)?[/QUOTE]

  I wouldn't. I also wouldn't use C99 comments, especially on Usenet.
[QUOTE]
for(int i=0; i<sizeof(f)/sizeof(f[0]); ++i)[/QUOTE]

  I'd also declare `i` outside of `for`, but that may be a matter of
taste.
[QUOTE]
Init(f[i]);
return 0;
}

Any better ideas?

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

Gernot Frisch

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.
 
V

Vladimir Oka

Gernot said:
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).
 
T

Thad Smith

Gernot said:
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);
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.
 
R

Roberto Waltman

Gernot Frisch said:
since C does not support construcor functions for structs, what is the
usual approach to write this C++ code in C:
Code:
struct foo
{
foo() {bar=0;}
int bar;
};

int main()
{
foo f[5];
}

I would write:
Code:
struct foo
{
bar;
};

Init(foo& f)
{
bar=0;
}

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;
}

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;
}

....
 
G

Gernot Frisch

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)
 
I

Ian Collins

Gernot said:
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.
 
P

pete

Ian said:

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.
 
R

Roberto Waltman

Gernot Frisch said:
...
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.
 
I

Ian Collins

pete said:
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.
 
T

Tom Plunket

Gernot said:
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!
 
K

Keith Thompson

Ian Collins said:
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.)
 
I

Ian Collins

Keith said:
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,
 
G

Gernot Frisch

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,184
Messages
2,570,976
Members
47,536
Latest member
MistyLough

Latest Threads

Top