c - VLA 原型和多维数组参数
问题描述
我这样创建了一个 C99 VLA 函数:
void create_polygon(int n, int faces[][n]);
我想在另一个函数中调用这个函数,我将在其中分配我的二维数组:
void parse_faces()
{
int faces[3][6];
create_polygon(6, faces);
}
当我将二维数组作为参数传递时,它会传递一个指向 6 整数数组的指针,引用调用函数中的堆栈内存。
这里的 VLA 参数仅充当类型声明(不分配任何实际内存),告诉编译器以行优先顺序访问数据,((int*)faces)[i * 6 + j]
而不是faces[i][j]
.
使用 VLA 参数或固定大小声明函数有什么区别?
解决方案
faces[i][j]
always等价于*(*(faces + i) + j)
,无论是否 VLA。
现在让我们比较两个变体(不考虑您实际上还需要外部维度来防止迭代时超出数组边界):
void create_polygon1(int faces[][6]);
void create_polygon2(int n, int faces[][n]);
传递给最初的数组是创建为经典数组还是 VLA 都没有关系,第一个函数接受长度正好为 6 的数组,第二个函数可以接受任意长度的数组(假设到目前为止这很清楚......)。
faces[i][j]
现在将被翻译成:
*((int*)faces + (i * 6 + j)) // (1)
*((int*)faces + (i * n + j)) // (2)
差异看起来微不足道,但在汇编程序级别可能会变得更加明显(假设所有变量都存储在堆栈中;假设sizeof(int) == 4
):
LD R1, i;
LD R2, j;
MUL R1, R1, 24; // using a constant! 24: 6 * sizeof(int)!
MUL R2, R2, 4; // sizeof(int)
ADD R1, R2, R2; // index stored in R1 register
LD R1, i;
LD R2, j;
LD R3, m; // need to load from stack
MUL R3, R3, 4; // need to multiply with sizeof(int) yet
MUL R1, R1, R3; // can now use m from register R3
MUL R2, R2, 4; // ...
ADD R1, R2, R2; // ...
当然,真正的汇编代码可能会有所不同,特别是如果您使用允许在寄存器中传递一些参数的调用约定(然后可能不需要将 n 加载到 R3 中)。
为了完整性(由于评论而添加,与原始问题无关):
还有这种int* array[]
情况:由指向数组的指针数组表示。
*((int*)faces + (i * ??? + j))
不再起作用,因为faces
在这种情况下没有连续的内存(当然,指针本身在连续的内存中,但不是全部faces[i][j]
)。我们被迫这样做:
*(*(faces + i) + j)
因为我们需要在应用下一个索引之前取消引用数组中的真实指针。汇编代码(为了比较,首先需要一个更完整的指向 2D 数组 case 的指针的变体):
LD R1, faces;
LD R2, i;
LD R3, j;
LD R4, m; // or skip, if no VLA
MUL R4, R4, 4; // or skip, if no VLA
MUL R2, R2, R3; // constant instead of R3, if no VLA
MUL R3, R3, 4;
ADD R2, R2, R3; // index stored in R1 register
ADD R1, R1, R2; // offset from base pointer
LD R1, [R1]; // loading value of faces[i][j] into register
LD R1, faces;
LD R2, i;
LD R3, j;
MUL R2, R2, 8; // sizeof(void*) (any pointer)
MUL R3, R3, 4; // sizeof(int)
ADD R1, R1, R2; // address of faces[i]
LD R1, [R1]; // now need to load address - i. e. de-referencing faces[i]
ADD R1, R1, R3; // offset within array
LD R1, [R1]; // loading value of faces[i][j] into register
推荐阅读
- c++ - 如何在列表末尾添加尾元素
- python-2.7 - 在 one-hot-encoding 数据集上使用 keras 的 2D-CNN 模型
- ios - 导航标题不显示
- laravel - 无法将选择值添加到输入组件 laravel
- excel - 根据另一个单元格中的值自动填充 VBA
- runtime-error - 从最大堆栈错误中保存 do 块中似乎无用的保护
- java - 如何使用 StringUtils 获取 UpperCamelCase?
- python - 如何在浮点数上合并数据框?
- c++ - boost::asio::ip::tcp::endpoint 的无序集 - 试图引用已删除的函数
- mysql - 每个订单的价格显示为订单价格