将参数传递给函数以有效地创建在堆栈上分配的数组

时间:2017-07-22 08:44:10

标签: c arrays performance

我有一个需要外部参数的函数,然后创建在该函数中大量使用的变量。例如。代码可能如下所示:

void abc(const int dim);

void abc(const int dim) {
    double arr[dim] = { 0.0 };
    for (int i = 0; i != dim; ++i)
        arr[i] = i;
    // heavy usage of the arr
}

int main() {
    const int par = 5;
    abc(par);
    return 0;
}

但我收到编译器错误,因为堆栈上的分配需要编译时常量。当我尝试使用_malloca在堆栈上手动分配时,代码的时间性能变差(与我在abc()函数中声明常量par的情况相比)。而且我不希望数组arr在堆上,因为它应该只包含少量的值,并且它会在函数内经常使用。有没有办法结合效率,同时保持将数组的size参数传递给函数的可能性?

编辑:我正在使用MSVC编译器,我收到错误C2131:表达式在VC 2017中没有评估为常量。

2 个答案:

答案 0 :(得分:3)

如果您正在使用现代C编译器,它实现了整个C99或具有可变长度数组扩展的C11,那么只需稍加修改就可以了:

void abc(const int dim);

void abc(const int dim) {
    double arr[dim];
    for (int i = 0; i != dim; ++i)
        arr[i] = i;
    // heavy usage of the arr
}

int main(void) {
    const int par = 5;
    abc(par);
    return 0;
}

即。 double arr[dim]可以工作 - 它没有编译时常量大小,但足以在运行时知道它的大小。但是,这样的 VLA 无法初始化。

不幸的是,MSVC不是一个现代的C编译器/ MS他们不想自己实现VLA - 我甚至怀疑它们是VLA制作原因的重要组成部分< C11中的em> optional ,因此您需要在main中定义数组,然后将指针传递给函数abc;或者如果大小是全局常量,则使用实际的编译时常量,即#define

但是,您没有显示您遇到性能问题的实际代码。如果它知道迭代次数,那么编译器可以产生优化的输出 - 如果这是真的,那么&#34;全局定义的大小&#34;可能是获得优异表现的唯一途径。

答案 1 :(得分:0)

不幸的是,Microsoft编译器不支持可变长度数组。

如果数组不是太大,您可以按所需的最大可能大小进行分配,并将指针传递给该堆栈数组和函数的维度。这种方法可以帮助限制分配数量。

另一种选择是为这种类型的函数实现一个简单的堆分配全局池。池将在堆上分配一个大的连续块,然后您可以在池中获得指向您的预留的指针。这种方法的好处是你不必担心堆栈上的过度分配导致分段错误(可能发生在可变长度数组中)。