-3

I wondering what the best solution is for a structure with variable length array for one of the fields. I've done a bunch of research and I haven't seen a clear answer yet. I've been playing with the below code and trying to get the varField to be set to an array the size of 10 bytes.

typedef struct TestStruct{
    int size;
    unsigned char varField[1];
}

I have tried doing zero sized array and that gives me a compile error. I also tried something like this and it gave me a compile error.

int size= 10;
struct TestStruct*test = malloc(sizeof(struct TestStruct) + (size- 1));
test->size= size;

Thank you so much for help.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
user3470688
  • 539
  • 6
  • 21
  • 3
    Is there some compelling reason to not use a standard container? – shuttle87 Jun 17 '14 at 15:35
  • 3
    "`malloc`" makes me cringe. – Baum mit Augen Jun 17 '14 at 15:35
  • 1
    Flexible arrays is [not part of C++ except by extension](http://stackoverflow.com/a/22608418/1708801) if this is C99 instead use [this method](http://stackoverflow.com/a/20221073/1708801). – Shafik Yaghmour Jun 17 '14 at 15:36
  • 1
    You say "C++" but this code is entirely C, with conventions that C++ has abandoned. – Drew Dormann Jun 17 '14 at 15:36
  • 2
    Are you sure your code is C++ and not C? – David Heffernan Jun 17 '14 at 15:36
  • I am using C++. I just playing around with different ways of converting message fields to a byte message. But I don't know the size of the one field until runtime. Can I do a class that will map directly to bytes that won't include overhead of the class??????? – user3470688 Jun 17 '14 at 15:42
  • That last question makes no real sense to me. Adding lots of question marks doesn't make it any clearer. I think you need to try to explain the real problem and let people guide you to a good solution. This looks like an XY problem where you decide what the solution is without telling us the problem. What is your real underlying problem? – David Heffernan Jun 17 '14 at 15:44
  • I have a structure that needs to be in a certain format for a certain message ICD. In the ICD byte 1 has to be lenght. The next field is a variable length field based upon the lenght. But I don't know this lenght until runtime. I know with a structure, if the size was NOT variable, how to convert this structure to a byte array. But since I don't know the size of one of the fields and if I just use a Vector, and convert it to bytes, you are going to have all the vector object as part of the message. how do I get ALL of the bytes for the stcructure at one time. – user3470688 Jun 17 '14 at 15:55

5 Answers5

2

The preferred way is to use the dynamically re-sizable std::vector. This class has the rule of five built in.

struct TestStruct {
    std::vector<unsigned char> varField;
}

If you're allergic to the standard library, you could use:

unsigned char *varfield;

And supply the necessary constructors/destructors.

yizzlez
  • 8,757
  • 4
  • 29
  • 44
1

If you are implementing messages, a better solution is to set up a hierarchy:

struct Message_Base
{
  unsigned int message_length_in_bytes;
  unsigned int message_id;
  virtual Checksum_Type calculate_checksum(void) = 0;
  virtual bool send_message(Receiver& r) = 0;
  virtual bool receive_message(Sender& s) = 0;
  virtual void process_message(void) = 0;
};

Each child class would be a different message with possible different lengths. Some possible common methods to all message are listed.

This is how to implement using Object Oriented and C++.

The class C language implementation is to declare a zero length array at the end for the message's unique data.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

You look like you want a std::vector<unsigned char>:

struct TestStruct{
    std::vector<unsigned char> varField;
}

and you get the size with:

ts.varField.size();
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
0

You can't. In C++ dynamic size arrays are illegal. The size of an array must be a compile time constant expression.

The options you have basically are

  1. Use an STL container like std::vector or the like. The benefits are that they also take care of memory allocation and deallocation for you.
  2. Use a pointer in your struct and allocate the memory for it dynamically. Don't forget to use delete[] instead of just delete!
sigy
  • 2,408
  • 1
  • 24
  • 55
0

In most compilers, the following will work:

template<unsigned N>
struct TestStruct {
  unsigned size = N;
  unsigned char varField[N];
};
struct ITestStruct {
  unsigned size;
  unsigned char varField[1]; // variable
};

template<unsigned N>
ITestStruct* make_test_struct() {
  return reinterpret_cast<ITestStruct*>(new TestStruct<N>());
};
ITestStruct* make_test_struct( unsigned n ) {
  char* buff = new char[ sizeof(ITestStruct)+n-1 ];
  ITestStruct* retval = reinterpret_cast<ITestStruct*>(buff);
  retval->size = n;
  return retval;
}

If you replace char with another non-POD type, things will get hairy.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524