严格来说,关于使用指向浮点数的指针的答案在技术上是不正确的,因为浮点数的二维数组与指向浮点数的指针的指针不同。
这将是等效的 C 代码:
#include <stdlib.h>
float (*transpose(int m, int n, float Xy[m][n]))[5000][3000] {
float (*result)[5000][3000] = malloc(sizeof(*result));
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
(*result)[i][j] = Xy[j][i];
}
}
return result;
}
这适用于指针:函数内的第一行为 5000 x 3000 的二维数组分配空间,按照 Java 代码中的方式进行复制,然后返回指向新数组的指针。请注意,一旦使用完内存,您就必须释放它(通过调用free()
).
该函数返回一个指向数组的指针,这意味着您必须像这样使用它:
float (*array)[5000][3000] = transpose(m, n, Xy);
然后就可以访问元素了i,j
从新数组中使用(*array)[i][j]
.
要释放,你可以这样做:
free(array);
最后,记住在 C99 支持下编译它 - 你需要它是因为可变长度数组Xy
在参数列表中。如果您使用 gcc,可以通过以下方式实现-std=c99
其他答案中提出的解决方案可能足以满足您的目的,但请记住,使用float **
因为二维数组有一些警告和“陷阱”。例如,与float **
解决方案,您必须手动释放中的每个位置array[i]
释放之前array
本身;sizeof
不会告诉您“模拟”二维数组的真实大小,并且浮点数不会连续存储在内存中。
2)我见过通常用C编写这种操作
没有返回类型方法,例如void 操作的方法
常量或者代码直接写在main中。为什么?
直接编写代码的部分main()
并不是很常见。也许您刚刚看到了一些教程示例。在更大的程序中,一般来说,这当然不在内部main()
.
如果您不想分配内存,那么在不带返回类型的情况下编写它可能会很有用:您可以将其留给调用者。这很重要,因为您不会将释放分配的内存的负担交给调用者。相反,您会收到一个由调用者提供给您的指向已分配内存缓冲区的指针,并将结果写入其中。在内存管理方面,这通常是一种优越的方法,但当然,大量的设计选择和小细节可以很快改变这一点。
UPDATE(如何在没有C99支持的情况下编译它):
嗯,这里的问题是Xy
可能是任意长度的二维数组,即你想调用transpose()
with any二维数组(这就是为什么你要给它m
and n
对于尺寸)。
C 没有直接方法将任意大小的二维数组传递给函数。 C99 中添加了此类支持。如果您想在 C89 中执行此操作,一个已知的解决方法是利用数组在连续内存位置中线性布局的事实,从而将其视为一维数组m*n
漂浮。换句话说,您可以滚动自己的索引。由于 C 数组按行优先顺序存储,Xy[i][j]
是相同的Xy_flat[i*n+j]
。所以,实际上,transpose()
接收指向第一个元素的指针Xy
,并对待Xy
作为一维数组。我们只需更换Xy[i][j]
with Xy[i*n+j]
:
/* C89 version */
#include <stdlib.h>
float (*transpose2(int m, int n, float Xy[]))[5000][3000] {
float (*result)[5000][3000] = malloc(sizeof(*result));
int i, j;
for(i = 0; i < m; i++) {
for(j = 0; j < n; j++) {
(*result)[i][j] = Xy[j*n+i];
}
}
return result;
}
对于来自 Java 的人来说,这可能看起来很奇怪且不平凡,但 C 通常在较低级别上工作。
要使用这个函数,你必须给它一个指向第一个元素的指针Xy
。这是一个例子:
float matrix[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
float (*transposed)[5000][3000] = transpose(3, 3, &matrix[0][0]);
/* Use (*transposed)[i][j]... */
free(transposed);
如果你不想和(*array)[5000][3000]
由于固定的硬编码维度,您当然可以使用其他答案中的解决方案,但始终牢记指针与指针之间的差异float
和一个二维浮点数组。由于您似乎更喜欢这种方法,因此代码如下所示:
float **allocate_mem_m(int m, int n)
{
int i;
float **arr = malloc(n*sizeof(*arr));
for(i=0;i<n;i++)
{
arr[i]=malloc(m*sizeof(**arr));
}
return arr;
}
float **transpose(int m, int n, float Xy[]) {
int i,j;
float **result = allocate_mem_m(m,n);
for(i = 0; i < m; i++) {
for(j = 0; j < n; j++) {
result[i][j] = Xy[j*n+i];
}
}
return result;
}
我冒昧地改变了你的allocate_mem_m()
仅接收维度,并返回带有分配内存的指针。我认为当你使用时它开始变得有点过于复杂float ***
。那没有必要。
作为建议,我同样会添加一个free_mem_m()
简化释放分配内存的过程:
void free_mem_m(int m, float **array) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
free(array);
}
这是完整的代码清单:
#include <stdlib.h>
float **allocate_mem_m(int m, int n)
{
int i;
float **arr = malloc(n*sizeof(*arr));
for(i=0;i<n;i++)
{
arr[i]=malloc(m*sizeof(**arr));
}
return arr;
}
void free_mem_m(int m, float **array) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
free(array);
}
float **transpose(int m, int n, float Xy[]) {
int i,j;
float **result = allocate_mem_m(m,n);
for(i = 0; i < m; i++) {
for(j = 0; j < n; j++) {
result[i][j] = Xy[j*n+i];
}
}
return result;
}
以及一个示例用法:
int main(void) {
float Xy[3][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 } };
float **transposed = transpose(3, 3, &Xy[0][0]);
int i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
printf("%f ", transposed[i][j]);
printf("\n");
free_mem_m(3, transposed);
return 0;
}
注意transpose()
假设一个方阵(因为你分配了一个块n
职位为m
漂浮)。如果你想将其与矩形矩阵一起使用,则必须分配m
保持块n
相反,它会漂浮。
现场演示工作:http://ideone.com/CyNdpn http://ideone.com/CyNdpn
最后说明:将 2D 数组视为 1D 数组的技巧既古老又棘手;它通常被认为是不好的做法(在我看来),你应该避免这种聪明的代码。但如果您不想使用 C99 功能,那么您就只剩下这了。
对于感兴趣的读者,冒着成为垃圾邮件发送者的风险,我在我的博客中写了两篇关于将这个想法推广到具有 N 维的任意数组的文章。它对为什么需要这样做以及如何做进行了更深入的技术解释:http://codinghighway.com/?p=1159 http://codinghighway.com/?p=1159 and http://codinghighway.com/?p=1206 http://codinghighway.com/?p=1206