-2
char *readByteArray() {
    unsigned char l = readByte (); // reads one byte from the stream
    char ret[l + 1]; // this should not be done
    ret[0] = l; // or could also define a struct for this like {int length, char *data}
    readBytes((char *)&ret + 1, l);
    return (char *)&ret;
}

So the problem is, that I want to return an array, and the length of the array is determined by the function.

A better example of this would be the function I use for reading a string:

char *readString () {
    unsigned char l = readByte (); // reads one byte from the stream
    char ret[l + 1]; // +1 for null byte
    readBytes((char *)&ret, l); // reads l bytes from the stream
    ret[l] = '\0'; // null byte
    return (char *)&ret; // problem
}

If the length of the array would be determined before the function I could allocate the array outside the function and pass it as a parameter, but calling this:

unsigned char l = readByte ();
char ret[l + 1];
readString (&ret, l);

every time I want to read a string would kind of defeat the purpose of the function.

Is there an elegant solution for this on windows AND ATmega328 (STL is not available)?

19greg96
  • 2,592
  • 5
  • 41
  • 55
  • 1
    you return reference to local variable, which gets put back to stack as your function returns, resulting in Undefined Behaviour. Also `char ret[l + 1]` is not standard C++(just so you know), most likely compiler addition(Maybe this is different on arduino, because arduino doesnt use true C++) – Creris Oct 14 '14 at 20:27
  • 1
    Return `std::vector`. – Anton Savin Oct 14 '14 at 20:27
  • Is your question about C++ or C, by the way? – Anton Savin Oct 14 '14 at 20:29
  • @TheOne I know that, that's the problem, "Undefined Behaviour", that's my question, how to avoid it with the given circumstances? – 19greg96 Oct 14 '14 at 20:30
  • make it global variable, or return `char[]` – Creris Oct 14 '14 at 20:32
  • @AntonSavin c++, however, I'm pretty novice in this area. – 19greg96 Oct 14 '14 at 20:32
  • ret is a static object that will be destroyed when function returns. that is why you have a problem with return statement. – Tracer Oct 14 '14 at 20:34
  • @TheOne as far as I know, that is not allowed: see second answer here: http://stackoverflow.com/questions/4264304/how-to-return-an-array-from-a-method "It is not possible to return an array from a C++ function. 8.3.5[dcl.fct]/6: Functions shall not have a return type of type array or function[...] " – 19greg96 Oct 14 '14 at 20:34
  • @Tracer yes, I fully understand the problem, I'm asking for a solution – 19greg96 Oct 14 '14 at 20:34
  • @19greg96 Anton's comment is honestly a solid way to do this in-general. You could also use `std::string` as a result if it is indeed string data. Try to get out of the business of trying to manage raw pointers in C++. It should be avoided where at all possible (and it almost always *is* possible). – WhozCraig Oct 14 '14 at 20:42
  • @WhozCraig in the `readByteArray()` method, an array of bytes is returned. Does `std::string` handle `\0` bytes in the string well? There is also a function I'm working on, to return an array of strings, how would I go about doing that? – 19greg96 Oct 14 '14 at 20:45
  • yes, if you pass const char* into string's constructor, it will read everything until \0 is found – Creris Oct 14 '14 at 20:52
  • If you want to preserve `\0` use this constructor: `std::string::string (const char* s, size_t n);` And if it isn't string data `std::vector` will be more obvious solution. – magras Oct 14 '14 at 21:06
  • @PetrPervukhin sorry, I looked further into it, and STL is not available on the arduino (ATmega328), and I don't have enough flash memory to use third party libraries. I was thinking, would malloc be an option to allocate the memory and protect it from being freed once the function returns? – 19greg96 Oct 14 '14 at 21:11
  • @greg, can you simply allocate `char buf [UCHAR_MAX+1]` before calling this fucntion? – magras Oct 14 '14 at 21:19
  • Else you will need to implement some sort of `std::vector` or [sync read interface](http://linux.die.net/man/2/read). – magras Oct 14 '14 at 21:22

1 Answers1

2

One of the following options should work:

  1. Return a pointer to an array of char allocated from the heap. Make sure to delete the returned value in the calling function.

    char* readByteArray()
    {
       unsigned char l = readByte();
       char *ret = new char[l + 1];
       ret[0] = l;
       readBytes(ret + 1, l);
       return ret;
    }
    
  2. Return a std::vector<char>.

    std::vector<char> readByteArray()
    {
       unsigned char l = readByte();
       std::vector<char> ret(l);
       readBytes(ret.data(), l);
       return ret;
    }
    
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Awesome! Thank you! So by writing `new char[n]` the array will be allocated on heap memory and won't be dislocated once the function returns? Why is that the accepted syntax and why isn't there a modifier for this, or something more self-explanatory? – 19greg96 Oct 14 '14 at 21:22
  • @19greg96, yes to the first question. I don't clearly understand your second question. – R Sahu Oct 14 '14 at 21:46