views:

413

answers:

9

Is there any way to return an array from a function? More specifically, I've created this function:

char bin[8];

for(int i = 7; i >= 0; i--)
{
    int ascii='a';
    if(2^i-ascii >= 0)
    {
     bin[i]='1';
     ascii=2^i-ascii;
    }
    else
    {
     bin[i]='0';
    }
}

and I need a way to return bin[].

+8  A: 

You can't do that but you can:

  • return a dynamicaly allocated array - best owned by a smart pointer so that the caller does not have to care about deallocating memory for it - you could also return something like an std::vector this way.
  • populate an array/vector passed to you as an argument by pointer (suggested) or a non const reference.
RnR
+1 vote, good answer. Just something to clarify things up for Keand64, you can't return bin because the memory allocated to it will be free upon completition of the function, so you will either have to receive the array with the memory allocated elsewhere or use dynamic memory being careful to free it after you stop using it.
Javier
Or use a vector.
anon
@Neil: You might have a significant performance hit during the rvalue copy if you decide to return the object directly - theoreticaly the storage of the vector might be moved to the rvalue copy instead of copying but I'm rather sure that's not what will happen.
RnR
+2  A: 

You are really asking the wrong question. If you want to do string processing in C++, use the std::string and/or std::vector classes, not arrays of char. Your code then becomes:

vector <char> func() {
    vector <char> bin(8);
    for( int i = 7; i >= 0; i-- ) {
       int ascii='a';
       if ( 2 ^ i - ascii >= 0 ) {
          bin[i] = '1';
          ascii = 2^i - ascii;
       }
       else {
        bin[i] ='0';
       }
    }
    return bin;
}
anon
+3  A: 

Your array is a local variable allocated on the stack. You should use new [] to allocate it on the heap. Then you can just say: return bin;. Beware that you will have to explicitly free it with delete [] when you are done with it.

Zifre
An even better idea is to use new[] to create the array and delete[] to delete it.
anon
@Neil Butterworth - How is it different from what Zifre said?
Javier
In C++, new and delete are different from new[] and delete[]
anon
@Neil Butterworth: I assumed the OP was familiar enough with C++ that I could leave out the []s.
Zifre
Okay, I have edited it to add the []s.
Zifre
A: 

you need to pass array bin as an argument in your function. array always pass by address, therefore you dont need to return any value. it will automatically show you all changes in your main program

void FunctionAbc(char bin[], int size);


void FuncationAbc(bin, size)
{
for(int i = 7; i >= 0; i--)
{
    int ascii='a';
    if(2^i-ascii >= 0)
    {
        bin[i]='1';
        ascii=2^i-ascii;
    }
    else
    {
        bin[i]='0';
    }
}

}
Syed Tayyab Ali
+1  A: 

I think your best bet is to use a vector. It can function in many ways like an array and has several upsides (length stored with type, automatic memory management).

void Calculate( std::vector<char>& bin) {
  for(int i = 7; i >= 0; i--)
  {
    int ascii='a';
    if(2^i-ascii >= 0)
    {
        bin.push_back('1');
        ascii=2^i-ascii;
    }
    else
    {
        bin.push_back('0');
    }
  }
}
JaredPar
A: 

You'll want to pass by reference, as follows:

void modifyBin(char (&bin)[8])
{
    /* your function goes here and modifies bin */
}

int main() 
{
    char bin[8];
    modifyBin(bin);
    /* bin has been updated */
    return 0;
}
Joey Robert
A: 

I think that everyone else answered this one... use a container instead of an array. Here's the std::string version:

std::string foo() {
    int ascii = 'a';
    std::string result("00000000");
    for (int i=7; i>=0; --i) {
        if (2^i-ascii >= 0) {
            result[i] = '1';
            ascii = 2^i-ascii;
        }
    }
    return result;
}

I'm not really sure if 2^i-ascii is want you want or not. This will be parsed as (2 ^ (i - ascii)) which is a little strange.

D.Shawley
+1  A: 

If you want to return a copy of the array (might make sense for small arrays) and the array has fixed size, you can enclose it in a struct;

struct ArrayWrapper {
   char _bin[8];
};

ArrayWrapper func()
{
    ArrayWrapper x;

    // Do your stuff here using x._bin instead of plain bin

    return x;
}

Or just use a std::vector as has been already suggested.

Ari
+1  A: 

Similar implemented to @ari's answer, i want to say there is already a boost solution, boost::array solving your problem:

boost::array<char, 8> f() {
    boost::array<char, 8> bin;
    for(int i = 7; i >= 0; i--) {
        int ascii = 'a';
        if(2 ^ i-ascii >= 0) {
            bin[i] = '1';
            ascii = 2 ^ i-ascii;
        } else {
            bin[i] = '0';
        }
    }
}

...
boost::array<char, 8> a(f());

[I'm not sure what you want to do with that algorithm though, but note that i think you want to do 1 << i (bit-wise shift) instead of 2 ^ i which is not exponentiation in C++.]

Boost array is a normal array, just wrapped in a struct, so you lose no performance what-so-ever. It will also be available in the next C++ version as std::array, and is very easy to do yourself if you don't need the begin()/size()/data()-sugar it adds (to be a container). Just go with the most basic one:

template<typename T, size_t S>
struct array { 
    T t[S];
    T& operator[](ptrdiff_t i) { return t[i]; }
    T const& operator[](ptrdiff_t i) const { return t[i]; }
};

But as usual, use the tools already written by other people, in this case boost::array. It's also got the advantage of being an aggregate (that's why it has no user declared constructor), so it allows initializing with a brace enclosed list:

boost::array<int, 4> a = {{ 1, 2, 3, 4 }};
Johannes Schaub - litb