我最近开始编写C代码块作为我大学编程课程的一部分(所以你可以自由地假设我是一个完全白痴)。我正在尝试编写一个将2D数组的数据写入文件的函数,但是我遇到了困难。我在main中声明了数组,我将其x和y维度保存为#define
s,我想像我这样调用function()
;
include "function.h"
#define /* x_res, y_res */
int main(){
static unsigned char pic[x_res][y_res];
/* do some operations on pic*/
function(pic,x_res,y_res);
}
函数本身保存在头文件中,旨在包含在我的主.c文件的最顶层。它是这样的;
void function(unsigned char arry,int x_res,int y_res){
/* some calculations, declaring file pointer with fopen() */
for(int i=0;i<y_res;i++){
for(int j=0;j<x_res;j++){
fprintf(f,"%c",arry[i][j]);
}
}
}
我遇到行fprintf(f,"%c",arry[i][j]);
中的错误,说“下标值既不是数组也不是指针也不是向量”,这是假的,因为我知道arry
是一个数组。此外,如果我尝试用fprintf(f,"%c",arry[i*j+j]);
之类的东西替换所述行,则错误消失,但文件输出是乱码(我假设我只打印{{的第一维元素的地址1}})。
然后问题;为什么不能像他们的1D对应物一样访问2D数组,我该如何解决这个问题呢?我想,arry
会给出
int array[][]={{0,1},{2,3}};
,但事实并非如此 - 它会打印0,2,然后打印两个内存地址。
我已经尝试声明我的函数接受array[0] -> 0
array[1] -> 1
array[2] -> 2
array[3] -> 3
的参数,工作但不是我希望函数工作的方式。
我看过其他一些在线示例,但似乎很少有人遇到过类似的问题。我尝试了this question的一些答案,但事情再次起作用。例如,使用void function(unsigned char arry[*value of x_res*][*value of y_res*],x_res,y_res)
可以将数组作为2D(void function(unsigned char **arry,x_res,y_res)
)进行访问,但同样,与上面的示例一样,大多数值(所有不在第一列中的值)都是垃圾。< / p>
答案 0 :(得分:1)
在C99及更高版本中,可能有VLA
void function(int x_res, int y_res, int char[][y_res])
{
for(int i=0;i<x_res;i++)
{
for(int j=0;j<y_res;j++)
{
fprintf(f,"%c",arry[i][j]);
}
}
}
问题是在C11中支持VLA的实现是可选的(即,不需要C11编译器来支持它们)。并且C90(1990年的ISO C标准)肯定不支持VLA。
声明的数组在内存中是连续的,因此可以像平面1D数组一样对待。例如;
void function2(int x_res, int y_res, unsigned char *arr)
{
for(int i=0;i<x_res;i++)
{
for(int j=0;j<y_res;j++)
{
fprintf(f,"%c",arr[i*y_res + j]);
}
}
}
int main()
{
unsigned char x[10][20];
unsigned char y[10*20];
unsigned char *z = malloc(10*20*sizeof(*z));
/* initialise elements x, y, and z */
function2(10,20, (unsigned char *)x);
function2(10,20, &x[0][0]);
function2(10,20, y);
function2(10,20, z);
}
首次调用function()
时需要进行类型转换,因为unsigned char
的2D数组无法隐式转换为unsigned char *
。但是,x
的地址和x[0][0]
的地址具有相同的值,即使它们具有不同的类型。
使用这种技术的问题是,在编译时不会检查传递的维度(function2()
的前两个参数)。例如;
int xx[5][6];
function2(10, 20, (unsigned char *)xx); /* danger, Will Robinson!! */
function2(10, 20, &xx[0][0]); /* danger, danger!! */
将编译,但由于xx
的维度小于前两个参数告诉function2()
预期,将导致function2()
对两个调用都有未定义的行为。