Как бы вы представили байтовый массив и его размер? Я хотел бы хранить (в основной памяти или в файле) необработанные байтовые массивы (символы без знака), в которых первые 2/4 байта будут представлять его размер. Но операции с таким массивом выглядят не очень хорошо:
void func(unsigned char *bytearray)
{
int size;
memcpy(&size, bytearray, sizeof(int));
//rest of operation when we know bytearray size
}
Как я могу избежать этого? Я думаю о простой структуре:
struct bytearray
{
int size;
unsigned char *data;
};
bytearray *b = reinterpret_cast<bytearray*>(new unsigned char[10]);
b->data = reinterpret_cast<unsigned char*>(&(b->size) + 1);
И у меня есть доступ к размеру и части данных bytearray. Но все равно выглядит некрасиво. Не могли бы вы порекомендовать другой подход?
Вы эффективно заново изобретаете «Строка Паскаля». тем не мение
b->data = reinterpret_cast<unsigned char*>(&(b->size) + 1);
не будет работать вообще, потому что указатель указывает на себя, и указатель будет перезаписан.
Вы должны иметь возможность использовать массив с неопределенным размером для последнего элемента структуры:
struct bytearray
{
int size;
unsigned char data[];
};
bytearray *b = reinterpret_cast<bytearray*>(::operator new(sizeof (bytearray) + 10));
b->size = 10;
//...
::operator delete(b);
В отличие от std::vector
это на самом деле сохраняет размер и данные вместе, так что вы можете, например, записать их в файл за одну операцию. И местность памяти лучше.
Тем не менее, тот факт, что std::vector
уже протестирован и реализовано много полезных алгоритмов, что делает его очень привлекательным.
Если у вас нет веской причины поступить иначе, просто сделайте идиоматическую вещь и используйте std :: vector<символ без знака>,
я хотел бы использовать std::vector<unsigned char>
управлять памятью и написать функцию преобразования для создания некоторых iovec
как структура для вас в то время, когда вам нужна такая вещь.
iovec make_iovec (std::vector<unsigned char> &v) {
iovec iv = { &v[0], v.size() };
return iv;
}
С помощью iovec
Если вам нужно записать длину и данные в одном системном вызове, вы можете использовать writev
призыв к выполнению этого.
ssize_t write_vector(int fd, std::vector<unsigned char> &v) {
uint32_t len = htonl(v.size());
iovec iv[2] = { { &len, sizeof(uint32_t) }, make_iovec(v) };
return writev(fd, iv, 2);
}