0

I have the following data i need to add in the void buffer:

MyStruct somedata; // some struct containing ints or floats etc.
string somestring;

How do i do this?

This is my buffer allocation:

void *buffer = (void *)malloc(datasize);

How do i add first the somedata into the buffer (, which takes lets say 20 bytes), and then after 20 bytes comes the string which is variable size. I was thinking to read the structs byte by byte and add to buffer, but that feels stupid, there must be some easier way...?

Edit: i want this to equal to: fwrite( struct1 ); fwrite( struct2 ); which are called sequentially, but instead of writing to file, i want to write to a void buffer.

Edit 2: Made it working, heres the code:

char *data = (char *)malloc(datasize);

unsigned int bufferoffset = 0;

for(...){
    MyStruct somedata; // some POD struct containing ints or floats etc.
    string somestring;

    ... stuff ...

    // add to buffer:
    memcpy(data+bufferoffset, &somedata, sizeof(MyStruct));
    bufferoffset += sizeof(MyStruct);
    memcpy(data+bufferoffset, somestring.c_str(), str_len); 
    bufferoffset += str_len;
}

Anything to fix?

Newbie
  • 1,143
  • 5
  • 20
  • 30
  • 3
    (1) You shouldn't in C++. (2) If you have to, you should know exactly what you're doing. (3) If you need to ask, then that's an indication that #2 doesn't apply. In that case, refer to #1. – sbi Nov 13 '10 at 15:56
  • Preferably, you don't. @sbi: Excellent suggestions. – Puppy Nov 13 '10 at 15:56
  • i am saving data to file, so it must equal to using fwrite() sequentially. But because i made separate function for the operations, i find it cleaner if i give the data pointer to the function and it handles the saving... – Newbie Nov 13 '10 at 15:58
  • 1
    @Newbie: Is this C or C++? Decide for either one. The code will be vastly different for non-PODs than for PODs, so the question whether non-PODs are on the agenda, too, is very important. – sbi Nov 13 '10 at 16:00
  • i use c++ but if theres a c-answer its fine too, which one is better is what i choose to use then. – Newbie Nov 13 '10 at 16:02
  • I think you can not predict the size of the structure because of structure padding.Use sizeof() for it. –  Nov 13 '10 at 16:24
  • yes i am using sizeof() ! the example was just to show you that the size is a constant. – Newbie Nov 13 '10 at 16:32
  • Are you only storing `string`s in the `void` buffer? Or other datatypes as well? – John Dibling Nov 13 '10 at 17:52
  • i found out the correct meaning would be using char* buffer since it did indeed crash if i tried to use void* buffer... look at my edits at my question, heres the code i use now. – Newbie Nov 13 '10 at 19:11
  • Newbie, why are you using `malloc()`? Indeed, this being C++ (there's a `std::string`), why do you manually allocate at all? Why not put your data into a `std::vector`. – sbi Nov 13 '10 at 19:43
  • @sbi: i dont know how to save vector into file in one fwrite() command, especially a vector like this... it would probably save all the string data etc... when i only need the char array without null terminating mark. Note that i am not using this data to store information, its only created before saving it, and then freed after save. – Newbie Nov 13 '10 at 22:56
  • I use vector to edit/store that data, and then save it as a stream of bytes like this... – Newbie Nov 13 '10 at 23:01
  • @Newbie: You can `resize()` a vector and then have the equivalent of a manually allocated array. Access its data using `&v[0]`, which gives you a pointer to the first element of an array. The main difference is that `std::vector` takes care of deallocating the array all by itself. – sbi Nov 14 '10 at 00:32
  • so i would have to loop through the data and use fwrite() multiple times... thats what im trying to avoid here, and how im supposed to pass different kinds of vectors to one function without using templates... not to mention i have no clue how such templates are done – Newbie Nov 14 '10 at 12:34

3 Answers3

2
memcpy(buffer, &somedata, sizeof(MyStruct));
strcpy(buffer + sizeof(MyStruct), somestring.c_str());

Which will copy the string as a c string.

yorick
  • 1,474
  • 10
  • 8
  • Note that this answer also has a `c++` tag. What happens if Newbie's `string` refers to `std::string`? (His nick is "newbie", after all.) – sbi Nov 13 '10 at 15:59
  • doesnt the memcpy() work for c_str() as well? feels weird to use different functions to different datatypes – Newbie Nov 13 '10 at 16:00
  • @sbi: that's what the c_str() is for. @Newbie: you can use that too, if you want (in combination with somestring.size), but generally one uses strcpy to copy strings. – yorick Nov 13 '10 at 16:03
  • In `C`, the "problem" of using `memmove`/`memcpy` for strings is that the string needs to be scanned twice: once to calculate its length, and again to copy: `memmove(dst, src, strlen(src));` – pmg Nov 13 '10 at 16:06
  • also, if i do this in a loop, i must use `buffer += sizeof(MyStruct);` and then again `buffer += somestring.length();` ? – Newbie Nov 13 '10 at 16:10
  • @pmg, well, i already calculate the length (stored in MyStruct), so theres no performance difference – Newbie Nov 13 '10 at 16:17
  • @yorick: Sorry, I missed this. However, that's not oging to work for any type. – sbi Nov 13 '10 at 16:33
  • @Newbie: If it's really only PODs, this seems fine at a quick glance. – sbi Nov 13 '10 at 17:21
0

In C, I'd do a bit like this:

MyStruct somedata;
string somestring;
void *buffer = (void *)malloc(datasize);

memmove(buffer, &somedata, 20);
strcpy(buffer + 20, somestring);

But there's LOTS of bad smell in the first 3 lines of this C code:

  • MyStruct is either a typedef (why? I hate typedefs) or it should be struct MyStruct
  • string is either a typedef (why? I hate typedefs) or it should be struct string; and identifiers starting with "str" are reserved and should not be used by programmers
  • Casting the return value of malloc is redundant and may hide errors

Edit after noticing (thanks Newbie) operations on void *

char *buffer = malloc(datasize);

In C, void* and any other pointer type are assignment compatible in both directions, so there is no need to cast char * to void * when passing it to memmove() and friends.

memmove(buffer, &somedata, 20);
pmg
  • 106,608
  • 13
  • 126
  • 198
  • @DeadMG, according to the tags it's both C and C++ (whatever that means) – pmg Nov 13 '10 at 16:24
  • is there some other way to move the pointer than (buffer+20) instead of buffer += 20; ? i cant get buffer += 20; work at all :7 – Newbie Nov 13 '10 at 16:29
  • uh, seems like i have to cast it to char* instead of void* then the buffer += 20 works. any explanation for this? – Newbie Nov 13 '10 at 16:45
  • Ah! Of course, sorry --- operations on `void*` are not defined. The `buffer` type should really be `unsigned char *` instead. – pmg Nov 13 '10 at 16:46
  • Depending on the destination of your buffer, you may need to copy the string terminator. If the string is "foo", str_len is 3 but you need to copy 4 bytes (the 3 letters and the '\0') ... so `memcpy(..., str_len + 1)` and `bufferoffset += str_len + 1;` – pmg Nov 13 '10 at 17:21
  • Typedefs are good because they hide internal nature of data type so make a data abstraction. I hate retyping struct to union and back everywhere when data format is changed. – Vovanium Nov 13 '10 at 17:28
  • @Vovanium: if you're doing "data abstraction" in "C", at a basic level such as suggested by this question/answer, either you're not doing "data abstraction" or you're not doing "C" – pmg Nov 13 '10 at 17:37
  • @pmg: the string length is saved in the MyStruct before saving the string, so when i read this file, i add the null terminator on each read string, its not saved in the file. – Newbie Nov 13 '10 at 17:39
  • @pmg: Basic level data abstraction is data abstraction too. Such one may save a lot of work. And "c" is not locking you in single coding paradigm. – Vovanium Nov 13 '10 at 17:49
  • I hate typedefs which serve only to hide the `union` or `struct` or `enum` keyword *and do no data abstraction at all* --- is this better @Vovanium? – pmg Nov 13 '10 at 18:03
  • @pmg: Hiding wether data type is union or struct is __also data abstraction__. It makes possible to deal with data without need to know is it really struct or union. Standard fpos_t is excellent example for this: if libc does not support mb it may be long int, and with mb support it would be struct containing int and mbstate_t. And user doesn't feel the difference. – Vovanium Nov 13 '10 at 18:11
  • ...And typedef make program cleaner wiping much syntactic noise. – Vovanium Nov 13 '10 at 18:14
0

In general you should avoid doing this for classes which have custom copy-constructors etc. But if you have to and you know what you're doing, use memcpy

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • Armen; I think the important distinction is PODs vs. non-PODs. – sbi Nov 13 '10 at 16:34
  • @fahad: memcpy can generally be optimized a bit better, because it's a requirement that the source and destinations do not overlap (as is the case here), while memmove can be used to copy to overlapping source/destinations. So if you're sure the source and destination will not overlap, memcpy is generally better. – yorick Nov 13 '10 at 16:35
  • This time I chose the informal way. Because otherwise I had to explain what a POD is. But, as you recall, whichever way I choose, you just HAVE to tell me I should have chosen the opposite :)) – Armen Tsirunyan Nov 13 '10 at 16:36
  • @Armen: Yep, you have found out the way it works now. `:)` (Really, would you care to write a `c++-faq` POD Q/A? It would be nice to be able to link to it.) – sbi Nov 13 '10 at 17:22
  • @sbi: you mean to ask a question and answer it myself? – Armen Tsirunyan Nov 13 '10 at 18:52
  • @Armen: Yep. That's certainly a worthwhile topic for an FAQ. Would be handy to link to all the time. – sbi Nov 13 '10 at 19:39
  • @sbi: OK, I'll do it one of these days :) – Armen Tsirunyan Nov 13 '10 at 20:14
  • @Armen: Leave a link here @addressed to me, so that I see it. I'd hate to miss this. – sbi Nov 13 '10 at 20:24
  • @sbi: POD FAQ as promised :) http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-how-are-they-special – Armen Tsirunyan Nov 14 '10 at 15:38