我正在用C语言构建一个处理三维数组的系统,在我们的玩具例子中,这些数组的形状是3x 3x 2,我们把它们看作是二维的3x 3网格,每个网格包含一个数据数组。
有时我会想访问这样一个网格的某些子部分;特别是我想访问网格的行和对角线,更具体地说,给定一个坐标对数组,我想得到一个数组指针,该数组包含指向这些单元格内容的指针,我已经可以用我的函数subfinder
来实现,见下面的代码。
#include <stdio.h>
typedef char mygrid[3][3][2];
typedef char** subthing;
subthing subfinder(mygrid p_grid, int indeces[3][2]) {
static char* result_array[3];
int x, y;
for(int i=0; i<3; i++) {
x = indeces[i][0];
y = indeces[i][1];
char* new = p_grid[x][y];
result_array[i] = new;
}
return result_array;
}
int main() {
mygrid example_grid = {
{ {1, 1}, {1, 2}, {1, 3} },
{ {2, 1}, {2, 2}, {2, 3} },
{ {3, 1}, {3, 2}, {3, 3} }
};
printf("Original center is (%d, %d).\n", example_grid[1][1][0], example_grid[1][1][1]);
int diag_indeces[3][2] = {{0,0}, {1,1}, {2,2}};
subthing diagonal = subfinder(example_grid, diag_indeces);
printf("Diagonal is (%d, %d).\n", diagonal[1][0], diagonal[1][1]);
example_grid[1][1][0] = 7;
example_grid[1][1][1] = 8;
printf("Original center is (%d, %d).\n", example_grid[1][1][0], example_grid[1][1][1]);
printf("Diagonal is (%d, %d).\n", diagonal[1][0], diagonal[1][1]);
diagonal[1][0] = 0;
printf("Original center is (%d, %d).\n", example_grid[1][1][0], example_grid[1][1][1]);
printf("Diagonal is (%d, %d).\n", diagonal[1][0], diagonal[1][1]);
}
这里我的问题是,我希望我的typedef为subthing
,来更好地描述这样一个事实,即它所指向的东西总是具有3x 2的形状,或者甚至其具有长度3。(我总是从主网格中获取行或对角线。)因此,我想使用例如typedef char** subthing;
来代替typedef char** subthing;
。typedef char* subthing[3];
但是后者编译失败,函数类型定义错误显示在末尾.我不明白的是为什么在subfinder
函数中我可以声明返回的东西为static char* result_array[3];
,但是这不能作为函数本身的返回类型.
任何帮助或解释我在这里做什么将不胜感激!gcc errors:
test.c:6:10: error: ‘subfinder’ declared as function returning an array
subthing subfinder(mygrid p_grid, int indeces[3][2]) {
^~~~~~~~~
test.c: In function ‘subfinder’:
test.c:18:12: warning: return makes integer from pointer without a cast [-Wint-conversion]
return result_array;
^~~~~~~~~~~~
test.c: In function ‘main’:
test.c:30:25: error: invalid initializer
subthing diagonal = subfinder(example_grid, diag_indeces);
^~~~~~~~~
2条答案
按热度按时间6g8kf2rb1#
一个可能的想法是避免将数组作为对象返回,而是将其作为参数传递,并将其填充到函数中。您甚至可以根据需要对其进行typedef。
wz3gfoph2#
你可以全力以赴,只传递完全类型化的变量。通常情况下,正如你所知道的,当数组作为参数传递时,它们会被“调整”到指向第一个元素的指针。这就是你所哀叹的信息丢失的原因:数组长度在转换中丢失了。我们可以通过传递 pointers 到数组来防止这种情况。指针通过赋值和作为函数参数保留了它的完整类型信息(两者有相似的语义)。这使得编译器可以警告越界访问,例如,如果你在中的
subfinder()
末尾注解printf。缺点是在索引数组指针之前,必须解引用它,这会使表达式复杂化,特别是当数组元素反过来又是数组指针时,就像
diagonal
在main()
中的情况一样。指向数组的指针的特殊之处在于,它们与第一个元素具有相同的数值,唯一的区别是类型,这在指针递增或索引时会产生差异:因为指向的每个元素都是整个数组,所以它的“单位”是整个数组大小(而不是数组元素大小)。
注意,这不是非常惯用的C语言,我并不是真的建议你这么做。(我还认为Dennis里奇没有考虑到这种习惯用法,否则他会交换索引操作符
[]
和解引用操作符*
的优先级。)表达式变得笨拙且难以解析(我花了10分钟看我的代码,因为我错误地将(*(*diagonal)[0])[0]
括起来了)。这也只有在编译时知道数组维数的情况下才有可能。但是这里有一个完全类型化的解决方案。我使用符号常量表示维数,并使用typedef'尽我所能艾德,但您应该认识大部分代码。