1

I am trying to build a constructor-like function for structs in C. I'm best with languages built around object-oriented features, and adding object-oriented features to a bare-bones language is not my forte. Unfortunately, for this project, however, I am forced to use a variation of C.

The idea is to build a function with a parameter for each variable in the struct that needs to be initialized, along with a 'name' parameter for the name of the struct.

The biggest issue is that the variation of C I need to use is very limited in features. It doesn't seem to have dynamic memory allocation, among other things.

The goal code would be something like this:

typedef struct {
    int a;
    string b;
} TheStruct;

void newStruct(string name, int a, string b){
    TheStruct name;
    name.a = a;
    name.b = b;
}

This won't work, because the struct instantiated with be called 'name' rather than the value of the name variable. How, without using higher-level features not found in C like variable variables, could a struct be dynamically referenced this way in C?

TheEnvironmentalist
  • 2,694
  • 2
  • 19
  • 46
  • 3
    I'm afraid this does not make much sense... what are you trying to do with `name`? – Flavio Dec 16 '13 at 22:01
  • [This book](http://www.planetpdf.com/codecuts/pdfs/ooc.pdf) seems to have some ideas about OOP in C. – Kninnug Dec 16 '13 at 22:02
  • Name is to be the name of the struct – TheEnvironmentalist Dec 16 '13 at 22:06
  • The *name* of the struct? Put some extra code about how you intend to use this, since it's becoming even less clear :) – Flavio Dec 16 '13 at 22:13
  • `It doesn't seem to have dynamic memory allocation` ???? Are you sure of that? What compiler is that, some proprietary 80s abomination for embedded systems maybe starting with a K? – fvu Dec 16 '13 at 22:20
  • RobotC. The designers of the compiler and language tried to make it as child-safe as possible, and so all memory allocation is "handled" by the compiler and device firmware. It has a number of other weaknesses, too, but it's what I'm forced to use. – TheEnvironmentalist Dec 16 '13 at 22:23
  • @TheEnvironmentalist hmmm indeed - you could get around that by (ab)using arrays I guess. But as this language's capabilities seem to be seriously trimmed down wrt "full" C I think you better stick to the basics - otherwise I'd suggest to have a look a various HashMap alike collections that exist in C because they offer functionality that should more or less give you what you seem to want, but I'm not sure it's possible to implement these in RobotC, the thing just isn't designed for that kind of wild programming. – fvu Dec 16 '13 at 22:33
  • @TheEnvironmentalist I love being proven wrong: http://www.robotc.net/forums/viewtopic.php?f=15&t=4464&view=previous - a HashMap for RobotC – fvu Dec 16 '13 at 22:34
  • You shuold also take a look here how OOP is implemented in C. http://ooc-coding.sourceforge.net/ – oz123 Dec 17 '13 at 10:56

2 Answers2

2

Two choices:

  1. pass an struct TheStruct by reference to the newStruct method
  2. return a heap allocated struct (a pointer to a struct TheStruct from newStruct) which later you'll have to delete using free

The method could be something like this:

typedef struct {
    int a;
    string b;
} TheStruct;

void newStruct(TheStruct* st, string name, int a, string b){
    st->a = a;
    st->b = b;
}

or

TheStruct* newStruct(string name, int a, string b){
    TheStruct *res = malloc(sizeof(TheStruct));
    res->a = a;
    res->b = b;
    return res;
}

You can take a look at this tutorial which is very nice: Pointers in C++. Is for C++ but the basics are pretty much the same.

Paulo Bu
  • 29,294
  • 6
  • 74
  • 73
  • please don't cast the result of malloc –  Dec 16 '13 at 22:23
  • What's the best way to do it then in C? – Paulo Bu Dec 16 '13 at 23:10
  • In C you leave it out completely. A `void *` is implicitly converted to the type of the lvalue. Casting the result of `malloc()` potentially leads to subtle hidden errors when the definition of `malloc()` is implicit (K&R style for example). For a complete (and better explanation than I can do) see http://c-faq.com/malloc/mallocnocast.html and http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc –  Dec 16 '13 at 23:17
  • Thank you very much. I didn't knew this, updating the answer :) – Paulo Bu Dec 16 '13 at 23:53
0

You want to pass a TheStruct in by reference or return a pointer to a new struct.

void newStruct( TheStruct* s, int a, string b )
{
   if( !s )
      s = malloc( sizeof( TheStruct ) );

   s->a = a;
   s->b = b;
}

//or

TheStruct* newStruct( int a, string b )
{
    TheStruct* s = malloc( sizeof( TheStruct ) );
    s->a = a;
    s->b = b;
    return s;
}

NOTE: when using the second version, you will have to remember to clean up the memory since it is created on the heap. With the first version, TheStruct could be created on the stack or the heap. (I assume a and b are defined.)

TheStruct s1, *s2;
s2 = malloc( sizeof( TheStruct ) );
newStruct( &s1, a, b );
newStruct( s2, a, b );
// do stuff
free( s2 );

In the second version it would look like:

TheStruct *s3 = newStruct( a, b );
// do stuff
free( s3 );
clcto
  • 9,530
  • 20
  • 42