1

If I have a std::vector buffer that has room for 100 characters and I call a C function that will write a NULL terminated string like writestring(&buffer[0], buffer.size()) from what I've read that's ok if there is already data in buffer. But if the vector is empty the behavior is undefined. How do I get around that, can I write something to the buffer like "qwerty" and then call writestring() so that I know the behavior is always defined? What kind of storage do you guys use when calling C functions? I just read about .data but I don't know how common or portable that is.

Thanks

jleahy
  • 16,149
  • 6
  • 47
  • 66
loop
  • 3,460
  • 5
  • 34
  • 57
  • Unless you would dynamically allocate your buffer to an a size that isn't a-priori known ahead of time, there's not much gain to using vector over a simple array. – Edward Strange May 08 '12 at 20:17
  • 3
    @CrazyEddie - I disagree. With `std::vector` (or `std::array`) you get [value semantics](http://en.wikipedia.org/wiki/Value_semantics). I find this decreases stoopid bugs to the point that I *never* use naked arrays or naked pointers to first members. – Robᵩ May 08 '12 at 20:21
  • You can disagree all you want so long as you realize you're wrong. – Edward Strange May 08 '12 at 20:29
  • `.data()` is not portable and is basically the equivalent of `&buffer[0]` anyway. – AJG85 May 08 '12 at 20:47

3 Answers3

3

C++

std::vector<char> v;
v.resize(100);
writestring(&v[0], v.size());

C

void writestring(char*p, size_t len) {
  strncpy(p, "Doofi", len);
}

if the vector is empty the behavior is undefined. How do I get around that?

By passing a non-empty buffer. Use the .resize() method to quickly fill the vector, or construct it to be the right size initially: std::vector<int> v(100);.

What kind of storage do you guys use when calling C functions?

std::vector is a fine choice for this application. To C, it looks just like an array or a malloc'd region. But, realize that C's pointer is only valid as long as the vector is neither reallocated or destroyed.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • Well check this out I just read http://stackoverflow.com/questions/3829788/using-operator-on-empty-stdvector . Do you agree or disagree? Even if I resize the vector isn't it still empty, and isn't empty behavior undefined? – loop May 08 '12 at 21:13
  • A buffer that is `resize`d to a non-zero value is not empty, and taking the address of the first element is valid. A buffer that is `resize`d to zero elements is empty; taking the address of the first element is undefined behavior. As long as `100` != `0`, the above code is well-defined. (Yes, I agree with the conclusion of the referenced question: you mustn't take the address of the first element of an empty vector.) – Robᵩ May 09 '12 at 13:42
3

Resize the vector first:

buffer.resize(100);
writestring(buffer.data(), buffer.size());  // buffer.data() == &buffer[0]

Alternatively, construct the buffer with the desired size all in one go:

std::vector<char> buffer(100);
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

I think you should test that the buffer is not empty. If it is empty, don't call writestring.

Marlin Pierce
  • 9,931
  • 4
  • 30
  • 52