在任何函数之外声明的变量大小类型

时间:2009-09-16 19:29:19

标签: c++ compiler-construction function declare

声明二维数组时

int random[height][width];

然后在函数中使用它

void populate(int random[height][width], int x, int y)

给出在任何函数之外声明的错误变量大小类型。 我知道我做错了什么,而且它的东西很小。我的记忆力很差......

5 个答案:

答案 0 :(得分:4)

我现在要站出来告诉你多维数组在C或C ++中不值得大脑努力。使用一维数组(或者更好的标准容器)并编写索引函数要好得多:

inline int index (int x, int y)
{
  return x + y * width;
}

现在为您解决问题。 C ++不支持C99可变长度数组。编译器必须在编译时知道数组的大小。例如,以下内容将无效。

int dim = 4;
int ar[dim];

如果dimconst,那么它会起作用,因为编译器能够准确地告诉ar应该有多宽(因为dim的值不会更改)。这可能是您遇到的问题。

如果您希望能够在编译时更改大小,则需要执行更困难的操作,例如编写模板化引用。您不能将指针用于多维数组,因为它们在C / C ++中的布局方式。模板化示例可能看起来像以下偏差:

template <int Width, int Height>
void populate(int (&(&random)[Width])[Height], int x, int y);

这太丑了。

对于运行时,您需要使用new来分配数据,或使用容器类型。

答案 1 :(得分:1)

您无法在函数外部定义具有非常量维度(宽度,高度)的数组,即 - 不在堆栈框架中,因为在编译时不知道尺寸。您可以使用常量或动态分配它(在堆中或堆栈帧中)。

答案 2 :(得分:1)

当一个数组作为参数直接传递给一个函数(按值传递)时,它会衰减成一个指向数组第一个元素的指针。即使您可以在签名中清楚地读取数组的维度,编译器也会忽略这些维度。该行为与C兼容。

使用C ++,您可以通过引用传递数组,这不再是一个问题。

int extract_value( int (&a)[10][10], int row, int col ) {
   return a[row][col];
}
int main() {
   int a[10][10] = {};
   a[5][5] = 1;
   std::cout << extract_value( a, 5, 5 ) << std::endl;
   int b[5][5];
//   extract_value( b, 2, 2 ); // error: the function takes an array of 10x10
}

函数参数必须完全匹配,也就是说,它只需要一个10x10元素的数组。您可以通过模拟数组大小上的函数来消除该限制。一旦你到达它也类型:

template <typename T, int Rows, int Cols>
T extract_value( T (&a)[Rows][Cols], int row, int col ) {
   return a[row][col];
}
int main() {
   int a[5][7] = {};
   extract_value( a, 3, 4 );
   int b[8][2] = {};
   extract_value( b, 7, 1 ); // correct, the compiler matches sizes
   double c[4][4] = {};
   extract_value( c, 2, 2 ); // different types are allowed
}

这个解决方案仍然很麻烦,因为大小必须是编译时常量,并且数组必须是堆栈分配的。对此的解决方案是定义一些在缓冲区(线性)中获取动态内存的类,并且具有从N坐标系到1维数组的转换以获得值,如之前所建议的那样。您可以在此FAQ中获取有关如何执行此操作的一些提示,该操作符重载提供了2D矩阵的实现。实现后,您可以将其用作函数/方法的参数。

我的建议是遵循最后一条路径:将N维数组封装到一个提供转换为1D向量的类中(C ++ FAQ lite使用原始指针,我更喜欢STL容器)。

答案 3 :(得分:1)

我将用例如:

来说明

//全局

const int ARRAY_SIZE = 16 struct ArrayType_t arrayType[ARRAY_SIZE];

即使ARRAY_SIZE被声明为常量int,它的值也不会在编译时初始化,因此编译器不知道数组的大小并且给出了这样的错误。但是,如果您将其作为哈希定义 #define ARRAY_SIZE 16 struct ArrayType_t arrayType[ARRAY_SIZE] ===&gt;这是有效的,因为定义了ARRAY_SIZE 编译时,编译器可以在编译时知道数组的大小。

答案 4 :(得分:-1)

您可以使用以下内容:

void populate(int height, int width, int **random)
{
    //here you can work from random[0][0] to random[height][width]
}

然后你可以像这样使用它:

int main()
{
    int height=10;
    int width=20;
    int **myarray = new int*[height];
    for( int i=0; i< height; i++ ) myarray[i] = new int[width];
    populate( height, width, myarray);
}

但是,当然,你必须注意缓冲区溢出