5

Is there a better way to initialise C structures in C++ code?

I can use initialiser lists at the variable declaration point; however, this isn't that useful if all arguments are not known at compile time, or if I'm not declaring a local/global instance, eg:

Legacy C code which declares the struct, and also has API's using it

typedef struct
{
    int x, y, z;
} MyStruct;

C++ code using the C library

void doSomething(std::vector<MyStruct> &items)
{
    items.push_back(MyStruct(5,rand()%100,items.size()));//doesn't work because there is no such constructor
    items.push_back({5,rand()%100,items.size()});//not allowed either

    //works, but much more to write...
    MyStruct v;
    v.x = 5;
    v.y = rand()%100;
    v.z = items.size();
    items.push_back(v);
}

Creating local instances and then setting each member one at a time (myStruct.x = 5; etc) is a real pain, and somewhat hard to read when trying to add say 20 different items to the container...

1
  • 4
    are you looking for a solution in C or C++? Commented Jan 3, 2010 at 12:46

6 Answers 6

8

If you can't add a constructor (which is the best solution in C++03 but you probably have compatibility constraint with C), you can write a function with the same effect:

MyStruct makeAMyStruct(int x, int y, int z)
{
    MyStruct result = { x, y, z };
    return result;
}

items.push_back(makeAMyStruct(5,rand()%100,items.size()));

Edit: I'd have checked now that C++0X offers something for this precise problem:

items.push_back(MyStruct{5,rand()%100,items.size()});

which is available in g++ 4.4.

Sign up to request clarification or add additional context in comments.

2 Comments

btw: why not use an initialization list?
"...C++0X offers something..." does this feature have a name that I could use to search for more info?
8

You're looking for C99 compound literals. Example code:

struct foo *foo = malloc(sizeof *foo);
*foo = (struct foo){ bar, baz };

4 Comments

Sounds like a great solution, if it was supported by the compiler (VC++9) :(
this time, it's actually not the compiler's fault as compound literals are a C99 feature unsupported by C++; I misread your question and thought you were looking for a solution in C...
see stackoverflow.com/questions/1705147/… for some explanations and the C++0x syntax
Complain to MS that their C compiler is archaic because it is only supporting a twenty year old standard, not the ten year old replacement standard.
3

How about:

MyStruct v = {5, rand()%100, items.size()};
items.push_back(v);

3 Comments

So to do multiple things ill have to do v1,v2,v3,v4 etc, no way to reuse the one local?
If you have v1, v2, v3, and v4, you are stuck with writing something out 4 times - unless you want them to have the same value, in which case you can do simple assignments, of course. If you had v[0], v[1], v[2], v[3] and v[4], then you could use a loop instead.
I'm not 100% sure about this, but I think: MyStruct vs[2] = {{1, 2, 3}, {2, 3, 4}}; will work
3

Create a function to initialize it, similar to what a C++ constructor would do.

1 Comment

(+1) KISS answer from all perspectives.
2

Not clear what you are asking. In C++, the obvious solution is to give the struct a constructor:

struct MyStruct {
  int x, y, z;
  MyStruct( int ax, int ay, int az ) : x( ax ), y( ay ), z( az ) {}
};

4 Comments

he's looking for a solution in C
Then why's he tagged it C++? This is why I said I wasn't clear.
My guess is that he has headers which have to stay in C (legacy code shared between projects) but he want a convenient way of using the struct in C++.
The thing is its a struct in some legacy C code, so unless there is some way to retrospectively add the constructor (i.e. without breaking compatibility with the C library the struct is for, and ideally without editing the declaration in the c headers themselves)?
1

Another option is to derive from the struct and add a constructor there.

struct MyDerivedStruct : public MyStruct
{
    MyDerivedStruct(int xi, int yi, int zi)
    {
        x = xi;
        y = yi;
        z = zi;
    }
}

Then you can use this derived type in your own code and pass it to the C library when necessary. The language should take care of implicitly converting to MyStruct when appropriate.

As a bonus, you could also add other useful member functions, perhaps even wrapping many of the legacy C functions that use this type.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.