Returning a variable length array from a function

 ̄綄美尐妖づ 提交于 2019-12-23 06:12:16

问题


The following function "increment" add 1 to a number represented as an array.

int*  increment(int array[], int size, int *sizeLen)
{
    int temp[size+1];

    int carry = 0;
    carry = (array[size-1]+1)/10;
    temp[size] = (array[size-1]+1)%10;

    for(int i=size-2;i>=0;i--)
    {
        temp[i+1] = (array[i] + carry)%10;
        carry = (array[i]+carry)/10;
    }
    if(carry)
    {
        temp[0] = 1;
        *sizeLen = size+1;
        return temp;
    }
    else
    {
        *sizeLen = size;
        return (temp+1);
    }
}

int main()
{
    int array[] = {9,9,9};
    int length;
    int *res = increment(array, sizeof(array)/sizeof(int), &length);
    for(int i=0;i<length;i++)
    {
        cout << res[i] << " ";
    }
}

I know gcc supports variable length arrays and they are stored on stack. I expect temp to go out of scope once this function ends and the attempt to print the array in main should print garbage values. But in my case the actual values are printed. When does the variable length array declared in the function goes out of scope?


回答1:


The key here is indeed the storage duration of the array. It has automatic storage duration. The lifetime of variables with automatic storage duration ends the moment the scope they're are in is exited.

It does exactly as you expect. But nothing in C stops you from taking the address of a local object and returning it from the function.

Using that pointer is undefined behavior. It may appear to work, but the array is still for all intents and purposes "dead". Such pointers are known colloquially as "dangling pointers".


Well, the above is true for C. Since this is about the GCC extension, the same applies mostly, but may need to be taken with a grain of salt.




回答2:


This won't work. You are returning a pointer to a local array, which will be deleted (more likely over-written/re-used) as soon as the function returns.

The C++ way to do things like that is to use std::vector<>. For example (assuming that in your original size and sizelen referred to the number of elements in array and the returned, respectively)

std::vector<int> increment(std::vector<int> const&array)
{
    std::vector<int> temp(array.size());
    auto a = array.rbegin();
    auto b = temp.rbegin();
    auto carry = (*a+1)/10;
    *b = (*a+1)%10;
    for(++a,++b; a!=array.rend(); ++a,++b)
    {
        *b = (*a+carry)%10;
        carry = (*a+carry)/10;
    }
    if(carry) { // we must add another element into temp at the start
                // that cannot be done with vector, hence we must create
                // another vector. Note that this should rarely happen.
       std::vector<int> result(temp.size()+1);
       auto r = result.begin();
       *r = 1;
       std::copy(temp.begin(),temp.end(),++r);
       return result;
    } else
       return temp;
}

Note that your code would be much simpler if you had defined the order of digits the other way around, i.e. the least significant digit as the first element (index 0). Moreover, as your digits seem to be decimal, you could use a smaller type than int. In this case, the code would look like

std::vector<std::uint8_t> increment(std::vector<std::uint8_t> const&input)
{
    std::vector<std::uint8_t> result;
    result.reserve(input.size()+1);
    auto a = input.begin();
    auto carry = (*a+1)/10;
    result.push_back((*a+1)%10);
    for(++a; a!=input.end(); ++a)
    {
        result.push_back((*a+carry)%10);
        carry = (*a+carry)/10;
    }
    if(carry)
        result.push_back(1);
    return result;
}



回答3:


This is undefined behavior. The next time a program pushes to the stack, the data will be lost.

Don't rely on this for professional programs.




回答4:


You are right. temp does go out of scope, and it should print garbage values.

But sometimes it prints correct values. Because the local stack memory is not cleared/overrided immediately when current function ends.



来源:https://stackoverflow.com/questions/41823420/returning-a-variable-length-array-from-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!