在任何函数外部声明的可变大小类型

发布于 2024-08-05 19:31:29 字数 224 浏览 1 评论 0原文

当声明二维数组

int random[height][width];

然后在函数中使用它时,

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

会出现在任何函数外部声明的可变大小类型错误。 我知道我做错了,而且是小事。我只是记性不好...

when declaring the two dimensional array

int random[height][width];

and then using it in a function

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

gives the error variable-size type declared outside of any function.
I know I'm doing something wrong, and that its something small. I just have a bad memory...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

红衣飘飘貌似仙 2024-08-12 19:31:29

我现在要站出来告诉您,多维数组不值得在 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 来分配数据,或使用容器类型。

I'm going to step up right now and tell you that multidimensional arrays are not worth the brain effort in C or C++. You're much better off using single-dimensional arrays (or, better yet, standard containers) and writing an indexing function:

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

Now for your problem. C++ does not support C99 variable-length arrays. The compiler must know, at compile time, the size of the array. The following, for example, won't work.

int dim = 4;
int ar[dim];

If dim were const, it would work because the compiler would be able to tell exactly how wide ar should be (because the value of dim wouldn't change). This is probably the problem you're encountering.

If you want to be able to change the size at compile-time, you'll need to do something more difficult, like write a templated reference. You can't use a pointer for multidimensional arrays because of the way they are laid out in C/C++. A templated example might look like the following aberration:

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

This is ugly.

For run-time, you'll need to use new to allocate data, or use a container type.

淑女气质 2024-08-12 19:31:29

您不能在函数外部(即不在堆栈帧中)定义具有非常量尺寸(宽度、高度)的数组,因为尺寸在编译时未知。您必须使用常量或动态分配它(在堆中或在堆栈帧中)。

You can not define the array with non-constant dimensions (width, height) outside of the function, that is - not in the stack frame, because the dimensions aren't known at compile-time. You'd have use constants or allocate it dynamically (either in heap or in the stack frame).

暖阳 2024-08-12 19:31:29

当数组直接作为参数传递给函数时(按值传递),它会衰减为指向数组第一个元素的指针。即使您可以在签名中清楚地读取数组的维度,编译器也会忽略这些维度。该行为与 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 坐标系转换为一维数组以获得值,正如之前所建议的那样。您可以在此 中获取有关如何执行此操作的一些提示有关提供 2D 矩阵实现的运算符重载的常见问题解答。一旦实现了该功能,您就可以将其用作函数/方法的参数。

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

When an array is passed directly as parameter to a function (pass by value) it decays into a pointer to the first element of the array. Even if you can clearly read in the signature the dimensions of the array, those dimensions are ignored by the compiler. That behavior is compatible with C.

Using C++ you can pass the array by reference and that would not be a problem any more.

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
}

The function parameter must match exactly, that is, it only takes an array of 10x10 elements. You can take rid of that restriction by templating the function on the array sizes. Once you are at it also the type:

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
}

This solution is still cumbersome in that the sizes must be compile time constants, and the array must be stack allocated. The solution to this is defining some class that takes dynamic memory in a buffer (linear) and has a conversion from the N-coordinate system into the 1-dimensional array to obtain values, as it was suggested before. You can get some hints on how to do it in this FAQ about operator overloading that provides an implementation of a 2D matrix. Once you have that implemented, you can just use that as parameter to functions/methods.

My recommendation would be to follow this last path: encapsulate the N-dimensional array into a class that provides conversions into a 1D vector (the C++FAQ lite uses a raw pointer, I prefer STL containers).

嗼ふ静 2024-08-12 19:31:29

我将用一个例子来说明:

//globals

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

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

I shall illustrate with an eg:

//globals

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

Even though ARRAY_SIZE is declared as constant int it's value is not initialized at compile time and hence the compiler doesn't know the size of the array and is giving such an error. However if you make that as an hash define
#define ARRAY_SIZE 16
struct ArrayType_t arrayType[ARRAY_SIZE]
===> this works because ARRAY_SIZE is defined at
compile time and compiler can know the size of the array at compile time.

感情废物 2024-08-12 19:31:29

你可以使用这样的东西:

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

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

You can use something like this:

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

then you can use it like this:

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

but, of course, you will have to watch out for buffer overflows

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文