user2836797
user2836797

Reputation:

Loop through a vector and copy the elements into a C array

The project I am working on requires a bunch of translation from C++ concepts to C. In this use case, the caller is responsible for managing the memory buffer. He then calls the function and provides the array of type double and the amount of memory he allocated. Then the function fills his array buffer with all the doubles in the vector. This is my first shot at the function, but I am not sure if it is correct. Since I am not too familiar with C, I am sure there are mistakes. Am I doing this right? And how about adding the null terminating \0 at the end?

void getMoments(uint32_t & bufferSize,
                double * moments)
{
  if ( bufferSize < (vec.size() * sizeof(double)) + 1 )
  {
    // set error: bufferSize is not large enough to copy elements of vector.
  }

  typedef std::vector<double>::const_iterator it_type;

  for (it_type it = vec.begin(); it != vec.end(); ++it) 
  {
    double e = *it;
    std::memcpy(moments, &e, sizeof(double));
  }

  // How do I add the null terminating \0?
}

By the way, the bufferSize is passed by reference because FORTRAN is one client and the language requires everything be passed by reference.

What confuses me about C arrays is the notion (or lack of notion) of a pointer. How do we know where we are at in the C array? In other words, every time I call memcpy should it write starting at the beginning of the array, thus overwriting my previously written bytes?

Upvotes: 0

Views: 607

Answers (3)

CouchDeveloper
CouchDeveloper

Reputation: 19114

One possible solution:

#include <vector>
#include <algorithm>
...

int getMoments(uint32_t* bufferSize,
                double * moments)
{
    std::vector<double> vec = ...
    if (*bufferSize/sizeof(double) < vec.size())
        return -1;
    std::copy(vec.begin(), vec.end(), moments);
    return 0;
}

See also std::copy

Note: a "reference" is not available in C. Thus, your C API must pass parameter bufferSize as pointer.

Upvotes: 1

heinrichj
heinrichj

Reputation: 552

The pointer can be used as an output iterator:

if (bufferSize < vec.size() * sizeof(double))
{
  // error: buffer too small
  return;
}

std::copy(vec.begin(), vec.end(), moments);

Note: if you are passing a pointer to double, I would express the buffer/array size in terms of doubles as well, rather than chars (bytes).

Upvotes: 3

Alexander Dzyoba
Alexander Dzyoba

Reputation: 4199

I have no idea why you would ever need to null terminate array of doubles, so I removed it.

Full code:

void getMoments(uint32_t & bufferSize, double * moments)
{
    if ( bufferSize < (vec.size() * sizeof(double)) )
    {
        // set error: bufferSize is not large enough to copy elements of vector.
    }

    typedef std::vector<double>::const_iterator it_type;

    for (it_type it = vec.begin(); it != vec.end(); ++it) 
    {
        *moments++ = *it;
    }
}

Upvotes: 1

Related Questions