问题描述
最近,我开始编程 C
只是为了好玩。我在一个非常熟练的程序员 C#.NET
和的Java
台式机领域内,但这是谈到了有点太挑战我。
I recently started programming C
just for fun. I'm a very skilled programmer in C# .NET
and Java
within the desktop realm, but this is turning out to be a bit too much of a challenge for me.
我试图做一些事情为简单是从一个函数返回一个二维数组。我试着研究在网络这个,但它是我很难找到一些工作。
I am trying to do something as "simple" as returning a two-dimensional array from a function. I've tried researching on the web for this, but it was hard for me to find something that worked.
下面是我到目前为止所。它并不完全返回数组,它只是填充之一。但即使这样,不会编译(我相信的理由必须是显而易见的给你,如果你是一个熟练的 C
程序员)。
Here's what I have so far. It doesn't quite return the array, it just populates one. But even that won't compile (I am sure the reasons must be obvious to you, if you're a skilled C
programmer).
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
。
修改:这是试图定义常量时,编译器错误:
Edit: Here's a compiler error when trying to define the constant: http://i.imgur.com/sa4JkXs.png
推荐答案
C没有治疗最喜欢的语言阵列;你需要了解以下概念,如果你想在C数组工作。
C does not treat arrays like most languages; you'll need to understand the following concepts if you want to work with arrays in C.
除非它是的sizeof
或一元&放大器的操作;
运营商,或者是一个字符串字面存在用于初始化另一个数组在声明中,前$ p $型 T
N个元素的数组的pssion 的将被转换(衰变),以类型的前pression指针 T
,和前pression的价值将是第一个元素的地址的阵列。这个结果是不是左值;它不能是赋值的目标,也可以是一个操作数的 ++
或 -
运营商。
Except when it is the operand of the sizeof
or unary &
operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T
" will be converted ("decay") to an expression of type "pointer to T
", and the value of the expression will be the address of the first element of the array. This result is not an lvalue; it cannot be the target of an assignment, nor can it be an operand to the ++
or --
operators.
这就是为什么你不能定义一个函数返回一个数组类型;数组前pression将被转换为指针类型为收益
语句的一部分,而且,也没有办法分配结果另一个数组前pression反正。
This is why you can't define a function to return an array type; the array expression will be converted to a pointer type as part of the return
statement, and besides, there's no way to assign the result to another array expression anyway.
信不信由你,有这个坚实的技术原因;当他最初开发C,丹尼斯里奇借了很多概念,从B编程语言。 B为一个无类型的语言;一切都被存储为一个无符号字,或单元。存储器被视为单元的一个线性阵列。当你宣布一个数组作为
Believe it or not, there's a solid technical reason for this; when he was initially developing C, Dennis Ritchie borrowed a lot of concepts from the B programming language. B was a "typeless" language; everything was stored as an unsigned word, or "cell". Memory was seen as a linear array of "cells". When you declared an array as
auto arr[N];
B。将预留N细胞为数组的内容,与(绑定到改编
额外的电池来存储偏移的第一个元素基本上是一个指针一起,但没有任何类型的语义)。数组访问被定义为 *(ARR + I)
;您偏移从保存在地址
I
细胞并取消引用的结果。这对C很好工作,直到里奇开始增加结构类型的语言。他希望该结构的内容,不仅描述抽象的数据,但在物理上重新present位。他用的例子是像
B would set aside N "cells" for the array contents, along with an additional cell bound to arr
to store the offset to the first element (basically a pointer, but without any type semantics). Array accesses were defined as *(arr+i)
; you offset i
cells from the address stored in a
and dereferenced the result. This worked great for C, until Ritchie started adding struct types to the language. He wanted the contents of the struct to not only describe the data in abstract terms, but to physically represent the bits. The example he used was something like
struct {
int node;
char name[14];
};
他想留出2个字节为节点,紧跟着的是name元素14个字节。他希望这样的结构数组进行布局,这样你不得不其次是14个字节后面2个字节后面14字节,等他想不出一个好办法来处理数组指针2个字节,所以他得到了完全摆脱它。而不是留出存储指针,C简单地从数组前pression自己计算吧。这就是为什么你不能指定任何一个数组前pression;没有什么可以赋值的到的。
He wanted to set aside 2 bytes for the node, immediately followed by 14 bytes for the name element. And he wanted an array of such structures to be laid out such that you had 2 bytes followed by 14 bytes followed by 2 bytes followed by 14 bytes, etc. He couldn't figure out a good way to deal with the array pointer, so he got rid of it entirely. Rather than setting aside storage for the pointer, C simply calculates it from the array expression itself. This is why you can't assign anything to an array expression; there's nothing to assign the value to.
那么,你如何从一个函数返回一个二维数组?
So, how do you return a 2D array from a function?
您没有。您的可以的返回的指针的一个二维数组,如:
You don't. You can return a pointer to a 2D array, such as:
T (*func1(int rows))[N]
{
T (*ap)[N] = malloc( sizeof *ap * rows );
return ap;
}
这样做的缺点的方法是, N
必须在编译时是已知的。
The downside to this approach is that N
must be known at compile time.
如果您使用的是C99编译器或编译器C2011支持变长数组,你可以做类似如下:
If you're using a C99 compiler or a C2011 compiler that supports variable-length arrays, you could do something like the following:
void func2( size_t rows, size_t cols, int (**app)[cols] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...; // the parens are necessary
...
}
如果您还没有变长数组提供这样做,那么至少在列维度必须是一个编译时间常数:
If you don't have variable-length arrays available, then at least the column dimension must be a compile-time constant:
#define COLS ...
...
void func3( size_t rows, int (**app)[COLS] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...;
}
您可以分配内存改小到的东西,就像一个二维数组,但行不一定是连续的:
You can allocate memory piecemeal into something that acts like a 2D array, but the rows won't necessarily be contiguous:
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
。对于所有的实际目的,你可以使用这个,就好像是一个二维数组:
p
is not an array; it points to a series of pointers to int
. For all practical purposes, you can use this as though it were a 2D array:
int **arr = foo( rows, cols );
...
arr[i][j] = ...;
printf( "value = %d\n", arr[k][l] );
注意,C没有任何垃圾回收;你是负责清理自己的混乱。在前三种情况下,它很简单:
Note that C doesn't have any garbage collection; you're responsible for cleaning up your own messes. In the first three cases, it's simple:
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 );
在过去的情况下,因为你做两步分配,你需要做两步释放:
In the last case, since you did a two-step allocation, you need to do a two-step deallocation:
int **arr4 = func4( rows, cols );
...
for (i = 0; i < rows; i++ )
free( arr4[i] )
free( arr4)
这篇关于返回在C二维阵列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!