从函数

时间:2017-01-24 08:32:49

标签: c++ arrays gcc variable-length-array

以下功能"增量"将1添加到表示为数组的数字中。

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] << " ";
    }
}

我知道gcc支持variable length arrays并且它们存储在堆栈中。 一旦这个函数结束,我希望temp超出范围,并且在main中打印数组的尝试应该打印垃圾值。 但在我的情况下,打印实际值。 函数中声明的可变长度数组何时超出范围?

4 个答案:

答案 0 :(得分:1)

这里的关键确实是数组的存储持续时间。它具有自动存储持续时间。具有自动存储持续时间的变量的生命周期在它们退出的范围退出时结束。

它完全符合您的预期。但是C中没有任何内容阻止你获取本地对象的地址并从函数中返回它。

使用该指针是未定义的行为。它似乎可以工作,但阵列仍然适用于所有意图和目的&#34;死&#34;。这些指针通俗地称为&#34;悬挂指针&#34;。

嗯,以上情况适用于C.由于这是关于GCC扩展,大致相同,但可能需要采取一些盐。

答案 1 :(得分:1)

这不起作用。您将返回一个指向本地数组的指针,该函数将在函数返回后立即删除(更有可能被覆盖/重新使用)。

C ++这样做的方法是使用std::vector<>。例如(假设原始sizesizelen分别引用array和返回的元素数量

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;
}

请注意,如果您已经相反地定义了数字顺序,即最低有效数字作为第一个元素(索引0),则代码会更简单。此外,由于您的数字似乎是十进制数,因此您可以使用比int更小的数字。在这种情况下,代码看起来像

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;
}

答案 2 :(得分:0)

这是未定义的行为。程序下次推送到堆栈时,数据将丢失。

不要依赖此专业课程。

答案 3 :(得分:0)

你是对的。 temp确实超出了范围,它应该打印垃圾值。

但有时会打印正确的值。因为当前函数结束时不会立即清除/覆盖本地堆栈内存。