我最近开始编程C
只是为了好玩。我在一个非常熟练的程序员C# .NET
和Java
台式机领域内,但这是谈到了有点太挑战我。
我正在尝试做一些“简单”的事情,就像从函数中返回二维数组一样。我曾尝试在网络上对此进行研究,但是很难找到可行的方法。
到目前为止,这就是我所拥有的。它并没有完全返回数组,而是只填充了一个。但是即使那样也无法编译(如果您是熟练的C
程序员,我相信原因对于您来说必须显而易见)。
void new_array (int x[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
return x;
}
和用法:
int x[n][n];
new_array(x);
我究竟做错了什么?应该提到的n
是一个具有值的常数3
。
编辑:尝试定义常量时,这是编译器错误:http : //i.imgur.com/sa4JkXs.png
C不像大多数语言一样对待数组;如果要在C中使用数组,则需要了解以下概念。
除了当它是的操作数sizeof
或一元&
运算符,或者是字面被用来在声明另一阵列,初始化一个字符串表达型“的N元件阵列的T
将被转换(“衰变”)”到的表达键入“ pointer to T
”,则表达式的值将为数组第一个元素的地址。这个结果不是左值;它既不能是赋值的目标,也不能是++
或--
运算符的操作数。
这就是为什么您不能定义一个函数来返回数组类型的原因。数组表达式将作为return
语句的一部分转换为指针类型,此外,无论如何都无法将结果分配给另一个数组表达式。
信不信由你,这是有充分的技术理由的。最初开发C时,Dennis Ritchie借鉴了B编程语言的许多概念。B是一种“无类型”语言;一切都存储为一个无符号的单词或“单元格”。内存被视为“单元”的线性阵列。当您将数组声明为
auto arr[N];
B将为数组内容留出N个“单元”,并绑定一个附加单元arr
以存储到第一个元素的偏移量(基本上是一个指针,但没有任何类型语义)。数组访问定义为*(arr+i)
;您i
从存储在其中的地址偏移了单元格a
并取消了对结果的引用。这对于C语言非常有效,直到Ritchie开始向该语言添加结构类型为止。他希望结构的内容不仅可以抽象地描述数据,而且可以物理地表示位。他用的例子是
struct {
int node;
char name[14];
};
他想为节点预留2个字节,紧随其后的是为name元素预留14个字节。并且他希望布置这样一个结构的数组,以便您有2个字节,然后是14个字节,然后是2个字节,然后是14个字节,依此类推。他想不出一种处理数组指针的好方法,因此他完全摆脱了它。C不用为指针留出存储空间,而是简单地从数组表达式本身计算指针。这就是为什么您不能为数组表达式分配任何内容的原因。没有什么可将值分配给。
那么,如何从函数返回2D数组呢?
你不知道 您可以返回一个指向2D数组的指针,例如:
T (*func1(int rows))[N]
{
T (*ap)[N] = malloc( sizeof *ap * rows );
return ap;
}
这种方法的缺点是N
必须在编译时就知道。
如果使用支持可变长度数组的C99编译器或C2011编译器,则可以执行以下操作:
void func2( size_t rows, size_t cols, int (**app)[cols] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...; // the parens are necessary
...
}
如果没有可用的可变长度数组,那么至少列维必须是编译时常量:
#define COLS ...
...
void func3( size_t rows, int (**app)[COLS] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...;
}
您可以将内存零碎分配给类似于2D数组的对象,但是行不一定是连续的:
int **func4( size_t rows, size_t cols )
{
int **p = malloc( sizeof *p * rows );
if ( p )
{
for ( size_t i = 0; i < rows; i++ )
{
p[i] = malloc( sizeof *p[i] * cols );
}
}
return p;
}
p
是不阵列; 它指向指向的一系列指针int
。出于所有实际目的,您可以像使用2D数组一样使用它:
int **arr = foo( rows, cols );
...
arr[i][j] = ...;
printf( "value = %d\n", arr[k][l] );
注意,C没有任何垃圾回收;您负责清理自己的混乱情况。在前三种情况下,很简单:
int (*arr1)[N] = func(rows);
// use arr[i][j];
...
free( arr1 );
int (*arr2)[cols];
func2( rows, cols, &arr2 );
...
free( arr2 );
int (*arr3)[N];
func3( rows, &arr3 );
...
free( arr3 );
在最后一种情况下,由于执行了两步分配,因此需要进行两步取消分配:
int **arr4 = func4( rows, cols );
...
for (i = 0; i < rows; i++ )
free( arr4[i] )
free( arr4)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句