Select structure with zero length array using new

In C (using gcc), I can declare a variable-length structure, as shown below:

typedef struct ProtocolFrame
{
     uint8_t      op;
     uint32_t     address;
     uint16_t     size;
     uint8_t      payload[0];
} ProtocolFrame;

then I can select another frame:

ProtocolFrame *frA;
ProtocolFrame *frB;

frA = malloc(sizeof(ProtocolFrame) + 50);
frB = malloc(sizeof(ProtocolFrame));

In this example, frA has a payload field of up to 50 bytes, and frB has no payload

Can I do the same in C ++ using the new operator?

+5
source share
6 answers
template<size_t s>
struct ProtocolFrame
{
     uint8_t      op;
     uint32_t     address;
     uint16_t     size;
     uint8_t      payload[s];
} ProtocolFrame;

// specialize for no payload
template<>
struct ProtocolFrame<0>
{
     uint8_t      op;
     uint32_t     address;
     uint16_t     size;
} ProtocolFrame;

ProtocolFrame<50> *frA = new ProtocolFrame<50>;
ProtocolFrame<0> *frB = new ProtocolFrame<0>;

To decide what size at runtime, you can use the-new operator in collaboration with std::malloc:

void *buffer = std::malloc(sizeof(ProtocolFrame)+50);
ProtocolFrame *frA = new (buffer) ProtocolFrame;

You can also read this article on codeproject.com, which contains a complete sample.

+9

char *buf  = new char[sizeof(ProtocolFrame) + 50];   //pre-allocated buffer
ProtocolFrame *frA = new (buf) ProtocolFrame;  //placement new

// STUFF

frA->~ProtocolFrame();
delete [] buf;

frA, destructor ProtocolFrame buf

EDIT: , delete, . , . , , delete, MSV++. , frA- > ~ ProtocolFrame(); buf; ! .

+2

, std::vector.

class ProtocolFrame {
    // Invokes undefined behaviour if stuff is not POD.
    struct stuff {
        stuff(uint8_t lop, uint32_t laddress, uint16_t lsize)
            : op(lop), address(laddress), size(lsize) {
        }
        uint8_t op;
        uint32_t address;
        uint16_t size;
    };
    std::vector<uint8_t> payload;
public:
    ProtocolFrame(int payloadsize, uint8_t op, uint32_t address, uint16_t size)
        : payload(size + sizeof(stuff)) {
        new (&payload[0]) stuff(op, address, size);
    }
    // other methods here
    uint32_t GetAddress() {
        return ((stuff*)&payload[0])->address;
    }
    uint16_t GetSize() {
        return ((stuff*)&payload[0])->size;
    }
    uint8_t GetOp() {
        return ((stuff*)&payload[0])->op;
    }
    std::vector<uint8_t>::iterator begin() {
        return payload.begin() + sizeof(stuff);
    }
    std::vector<uint8_t>::iterator end() {
        return payload.end();
    }
};

.

+1

++ . ProtocolFrame , payload ?

struct ProtocolFrame {
   uint8_t      op;
   uint32_t     address;
   uint16_t     size;
   uint8_t      *payload;

   public:
       ProtocolFrame (int size) {
          payload = new uint8_t [size];
       }

       ~ProtocolFrame () {
          delete [] payload;
       }
 }
+1

, , operator new, . g++ 4.0.1 ( , "", ):

#include <cstddef>

template <typename T>
class test {
  public:
    std::size_t len;
    T arr[1];

    void *operator new(std::size_t s, std::size_t a);

    test(const T& f) { fill(f); }
    test();

  private:
    void fill(const T& f) { for(std::size_t i = 0; i < len; i++) arr[i] = f; }
};

template <typename T>
void *test<T>::operator new(std::size_t s, std::size_t a)
{
    void *p = ::operator new(s + (a - 1) * sizeof(T));
    // this is bad and we shouldn't do this here blah blah blah
    // but I don't know how to pass a to the ctor so this is what I did
    ((test<T> *)p)->len = a;
    return p;
}

:

#include <iostream>

int main()
{
    test<char> *c = new (10) test<char>('c');
    std::cout << c->arr[3] << std::endl;
    delete c;
    return 0;
}

new.

+1

C, , .

sizeof() .

payload ?

: .

EDIT2: @, , , 2 malloc... ,

inline ProtocolFrame * createProtocolFrame(int i)
{
    ProtocolFrame * pProto = malloc(sizeof(ProtocolFrame));
    pProto->payload = malloc(i * sizeof(uint8_t));
}
0

All Articles