Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 10 of 10
  1. #1
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Variable array inside struct

    Hi all,

    In C/C++, I'm trying to allow a variable length array inside a struct. Something like this:

    struct Mystate {
    double p[var];
    };

    A Mystate variable (or array) will be created with each one containing an arbitrary amount of elements for the array p. How do I do this?

  • #2
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    You will have to make it a pointer instead.

    Code:
    struct Mystate
    {
    
    double *p;
    };
    Then you would have to do something like:
    Code:
    int var = 6;
    
    Mystate ms1;
    ms1.p = new double[var];
    And that will create an array of size var.

    But remember then that you will be responsible for deleting that pointer before your program ends otherwise it will leak memory. In cases like this where you have to use dynamic memory allocation, you should really make it a class. That way you can have the destructor in the class delete the pointer and you won't have to worry about it. (Assuming of course that the instantiation of the class isn't dynamic too)

    Hopefully I didn't confuse you too much.
    OracleGuy

  • #3
    Regular Coder ralph l mayo's Avatar
    Join Date
    Nov 2005
    Posts
    951
    Thanks
    1
    Thanked 31 Times in 29 Posts
    Use a vector unless you've got a good reason not to. No need to worry about memory management, or even to guess how many elements you'll need in a given instance, although you can for slightly better performance. (Unless you guess too low, then slightly worse performance, but slightly worse performance is better than clobbering memory off the end of a pointer )

    Code:
    struct Mystate
    {
    	std::vector<double> p;
    };

  • #4
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    Good point. I didn't even think about using a vector. That'd probably will be your best bet. If you are using the Microsoft C++ compiler, the vector class will run painfully slow (compared to other data structures) when making a debug build but it runs fine in release.
    OracleGuy

  • #5
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hi all and thanks for all the comments!

    Vectors are tempting to use, but if the program knows how big the array is going to be, then surely there's an unnecessary speed overhead associated with vectors? Yes, I could use reserve(), but perhaps even then there's an overhead (?). Besides, I was hoping for pure C due to slower compilation times with C++.

    Also, the problem with using vectors or pointers is that it means the struct won't be fully self-contained. In other words, one needs to malloc or reserve outside the struct, when really I want a parameter passed to the struct to define how large the array inside the struct is going to be.

    The matter is even more ugly with an array of structs, since each array inside each struct will have to be malloced/reserved. Hope that makes sense.

    On the subject of using classes, that seems interesting, but slightly overkill, when structs will do everything I want really (just a fixed set of structures of data without any specific operations on that data).

    Ideally, I want something like this:

    struct Mystate(int myparam) {
    double p[myparam];
    };

    or this if I have to:

    struct Mystate(int param) {
    std::vector<double> p;
    p.reserve(param);
    };
    Last edited by twinbee; 08-06-2007 at 07:27 PM.

  • #6
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    Quote Originally Posted by twinbee View Post
    Ideally, I want something like this:

    struct Mystate(int myparam) {
    double p[myparam];
    };

    or this if I have to:

    struct Mystate(int param) {
    std::vector<double> p;
    p.reserve(param);
    };
    A class is exactly what you want then. It isn't overkill. (The vector class might but it really depends what you are doing)

    Code:
    class Mystate
    {
    public:
    
    Mystate(int count) { m_p = new double[count]; } Mystate() { m_p = 0; } ~Mystate() { delete m_p; } double* getP() { return m_p; } void reserve(int count) { delete m_p; m_p = new double[count]; }
    private: double *m_p; };
    And if you didn't want to use the getP method, you could overload the bracket operator very easily. That class is the basic idea, you could add a length property to if you really wanted to.

    If you want to do it in only C, you are going to have to do malloc the pointer in the struct manually. Or just make the array a fixed size, e.g.:
    Code:
    struct Mystate
    {
    double p[100];
    }
    Last edited by oracleguy; 08-06-2007 at 11:10 PM.
    OracleGuy

  • #7
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hi OracleGuy

    I can't believe I may actually use classes after all. (I actually have a slight aversion to objects/OO in general after being so used to procedural programming, and also the lessons on OO we were given in Java at uni, and also the seemingly overcomplicated private/public and way of retrieving variables - I much prefer "object[5].g" to "object[5].getGvar()".

    Nevertheless, I could give it a go. After searching for around 10-20 pages on Google, I couldn't find out how to combine:

    Myclass x[50]

    ....with passing a parameter (10 here) to every object's constructor aswell:

    Myclass x(10)[50] // (returns an error unfortunately).

    If we can solve that, and I can easily use qsort to sort the object array based on a variable inside the new class, then I might never use structs again.
    Last edited by twinbee; 08-06-2007 at 09:44 PM.

  • #8
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    Quote Originally Posted by twinbee View Post
    Hi OracleGuy

    I can't believe I may actually use classes after all. (I actually have a slight aversion to objects/OO in general after being so used to procedural programming, and also the lessons on OO we were given in Java at uni, and also the seemingly overcomplicated private/public and way of retrieving variables - I much prefer "object[5].g" to "object[5].getGvar()".
    When done right, OOP can be amazing great to program with. But I also can understand that if it was done horribly bad how it would seriously stink.

    Nevertheless, I could give it a go. After searching for around 10-20 pages on Google, I couldn't find out how to combine:

    Myclass x[50]

    ....with passing a parameter (10 here) to every object's constructor aswell:

    Myclass x(10)[50] // (returns an error unfortunately).

    If we can solve that, and I can easily use qsort to sort the object array based on a variable inside the new class, then I might never use structs again.
    Alright, well there are two ways to do this. If you'll look at the class you'll notice I made a default constructor that takes no parameters. I did that so you could do:
    Code:
    Mystate myArray[50]
    And then if you want to set the size, then you can use the reserve method in the class.

    Or if you don't want to have to loop through and call the reserve each time you can do:

    Code:
    Mystate ary[3] = {4, 7, 1}
    Also I noticed that there was an error in the code I posted for that class (which I have now fixed). I forgot the () on the destructor.


    Ok, now onto the qsort. That is fairly easy. If memory serves there is a callback function you use to check to see if two items are greater than or less than each other.

    To make it super easy you could overload the comparison operators on your class or just manually do the checks in your callback function.

    And of course to be totally proper there should be some more checks in that class to make sure you don't pass a negative count value (or switch to using an unsigned int).
    OracleGuy

  • #9
    Regular Coder ralph l mayo's Avatar
    Join Date
    Nov 2005
    Posts
    951
    Thanks
    1
    Thanked 31 Times in 29 Posts
    You can make a vector the size you want on construction, but that's getting into some rather egregious premature optimization. I'd still urge you to consider using a vector (or a set, which is always sorted at the cost of insertion speed) while you're trying new things.

    Code:
    class MyState
    {
    public:
    	MyState(size_t p_els)
    	{
    		// Linear time
    		p = new std::vector<double>(p_els);
    		ins_idx = 0;
    	}
    	~MyState() { delete p; }
    
    	inline void addp(double d)
    	{
    		// Constant time
    		(*p)[ins_idx++] = d;
    	}
    	inline double getp(size_t idx)
    	{
    		// Constant time
    		return (*p)[idx];
    	}
    	inline void sortp()
    	{
    		// Constant time
    		std::vector<double>::iterator it = p->begin();
    		// n log(n), like quicksort, but the worst case is also n log(n) whereas qsort decays to n^2
    		std::sort(it, it + ins_idx);
    	}
    private:
    	std::vector<double>* p;
    	size_t ins_idx;
    };
    All the constant time functions of course scale perfectly, you're not going to get any better than n log(n) on the sort, and if the linear time construction actually became a bottleneck, which I very much doubt since you'll be doing it comparatively infrequently, you can use a pool approach recycle pre-allocated vectors.

    ...unless you weren't talking about speed, in which case I don't get the meaning of std::vector being overkill. Don't worry about the tool being too good for the job. It's really the standard C++ array, and it's the C arrays that should be reserved for special occasions. (Since I gather you're going with C++ now, as you should if you want to make structures handle their own memory)
    Last edited by ralph l mayo; 08-07-2007 at 04:31 PM.

  • #10
    New Coder
    Join Date
    Aug 2007
    Posts
    13
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Regarding vectors vs. arrays:

    Arrays are faster. Get it working right first with a vector or whatever, then if it needs to run faster, profile it and determine that using arrays there would actually help. Your time should cost more than the computer's.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •