矩阵转置移植从Java到C,不兼容的类型问题 [英] Matrix transposition porting from Java to C, incompatible types issue

查看:155
本文介绍了矩阵转置移植从Java到C,不兼容的类型问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些端口Java方法在C,有Java背景,但我在C语言编程共小白

I have to port some Java methods in C, have a Java background but I'm a total noob in C programming

在Java的

float[][] traspose(float Xy[][]) {
    float result[][]=new float[5000][3000];
    for(int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            result[i][j] = Xy[j][i];
        }
    }
    return result;
}

我的C移植的尝试。

My C porting attempt

float traspose(int m, int n, float Xy[m][n]) {
    int i,j;
    float result[5000][3000];
    for(i = 0; i < m; i++) {
        for(j = 0; j < n; j++) {
            result[i][j] = Xy[j][i];
        }
    }
    return result;
}

这不工作,获得不兼容类型的错误。

This doesn't work and get incompatible types error.

我的2个问题

1)我应该如何解决我的code?
谷歌搜索我已经看到了关于用C返回矩阵,但不是很清楚,在大多数情况下,一些问题被建议使用不意味着使用回报的方法。

1) How should I fix my code? Googling I have seen some questions about returning matrix in C but not very clear and in most case was suggested to use an approach that doesn't imply the use of return.

2),我已经看到,通常这种在C这样的操作都没有返回类型的方法例如写上常量或code操作无效的方法在主直接写入。
为什么呢?

2) I have seen that usually this kind of operations in C are written without return type approach e.g. void methods that operate on constants or the code is written directly in main. Why?

修改

随着我试图code此建议

Following the suggestions I have tried to code this

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(int argc, char **argv) {
    printf("Hello World!");
    float matrix[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
    printf("Matrix created\n");
    int size=3;
    print(size, size, matrix);
    float **transposedmat = transpose(size, size, &matrix[0][0]);
    printMat(size, size, transposedmat);
    return 0;
}

但不幸的是,当我调用trasposition方法的程序崩溃。

But unfortunately the program crashes when I invoke trasposition method.

PS
我想编译标准C(不是C99)

PS I want to compile the code in standard C (not in C99)

推荐答案

严格地说,关于使用指针的指针浮在技术上不是正确答案,因为花车的二维数组是不一样的指针的指针的浮动。

Strictly speaking, the answers about using pointer to pointer to float are not technically correct, because a 2D array of floats is not the same as a pointer to pointer to float.

这将是等价的C code:

This would be the equivalent C code:

#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;
}

这可与指针:函数内部的第一行由3000分配为5000二维数组的空间,让你在你的Java code复制,并返回指向新数组。请注意,您必须释放内存,一旦你用它做(通过调用免费())。

This works with pointers: the first line inside the function allocates space for a 2D array of 5000 by 3000, makes the copy as you have in your Java code, and returns the pointer to the new array. Note that you have to free the memory once you are done with it (by calling free()).

该函数返回一个指针数组,这意味着你将不得不使用这样的:

The function returns a pointer to an array, which means you'll have to use it like this:

float (*array)[5000][3000] = transpose(m, n, Xy);

然后你就可以访问元素 I,J 使用新的数组(*数组)[I] [J]

要免费的,你这样做:

free(array);

最后,记得C99支持编译这个 - 你需要它,因为可变长度数组的 XY 中的参数列表。如果你正在使用gcc,这可以用 -std = C99

Finally, remember to compile this with C99 support - you need it because of the variable length array Xy in the parameters list. If you're using gcc, this can be achieved with -std=c99

在其他的答案提出的解决方案,可以为你的目的就足够了,但请记住,使用浮法** 作为一个二维数组有一些注意事项和陷阱。例如,与浮法** 的解决方案,你必须手动免费数组[我] 每个位置之前释放阵列本身; 的sizeof 不会告诉你的模拟二维数组的真实大小,花车将不会被存储在内存中连续。

The solution proposed in the other answers may be enough for your purposes, but keep in mind that using a float ** as a 2D array has a few caveats and 'gotchas'. For example, with the float ** solution, you'll have to manually free every position in array[i] before freeing array itself; sizeof will not tell you the true size of the "simulated" 2D array, and floats will not be stored in memory contiguously.

2),我已经看到,通常用C这类操作都写
  没有返回类型的方法例如上进行操作无效的方法
  常量或code是主直接写入。为什么呢?

2) I have seen that usually this kind of operations in C are written without return type approach e.g. void methods that operate on constants or the code is written directly in main. Why?

约code部分正在直接写的main()是不是很常见。也许你只是看到一些实例教程。在更大的项目,而在一般情况下,这是当然的,里面没有的main()

The part about code being written directly in main() is not very common. Maybe you just saw some tutorial examples. In bigger programs, and in general, this is, of course, not inside main().

写它没有返回类型可以是有用的,如果你不希望有分配内存:你离开,最多给调用者。这一点很重要,因为你不把你释放的来电者分配内存的负担。相反,您会收到调用者给你一个指向已分配内存缓冲区,并在那里写的结果。这通常是一个优越的做法,当涉及到内存管理,当然,大量的设计选择和小细节可以迅速改变这种状况。

Writing it without a return type can be useful if you don't want to have to allocate memory: you leave that up to the caller. This is important, because you don't place the burden of freeing memory you allocated on the caller. Instead, you receive a pointer to an already allocated memory buffer, given to you by the caller, and write the results in there. This is generally a superior approach when it comes to memory management, but of course, lots of design choices and little details can quickly change this.

更新(如何编译它不支持C99):

UPDATE (how to compile it without C99 support):

好了,这里的问题是, XY 可以是任意长度的二维数组,即,要呼叫转()的二维数组(这就是为什么你给它 M N 的尺寸)。

Well, the problem here is that Xy may be a 2D array of arbitrary length, i.e., you want to call transpose() with any 2D array (that's why you're giving it m and n for the dimensions).

C具有通过任意大小的二维阵列的函数的直接方式。在C99加入这样的支持。如果你想这样做的C89,已知的解决方法是使用一个事实,即阵列线在连续的内存位置奠定了,因此使用它,仿佛它是 M * n的一维数组浮动。换句话说,你滚你自己的索引。由于C数组存储在列优先的顺序, XY [I] [J] 相同 Xy_flat [I * N + J] 。所以,实际上,转()接收指向的第一个元素在 XY ,和对待 XY 作为一维数组。我们只需要替换 XY [I] [J] XY [I * N + J]

C has no direct way of passing arbitrarily sized 2D arrays to a function. Such support was added in C99. If you want to do this in C89, a known workaround is to use the fact that arrays are linearly layed out in contiguous memory positions, and thus use it as if it were a 1D array of m*n floats. In other words, you roll your own indexing. Since C arrays are stored in row-major order, Xy[i][j] is the same as Xy_flat[i*n+j]. So, in effect, transpose() receives a pointer to the first element in Xy, and treats Xy as a 1D array. We just have to replace 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的到来,但Ç通常工作在较低的水平。

This may seem weird and non trivial for someone coming from Java, but C usually works at a lower level.

要使用此功能,你必须给它一个指针 XY 的第一个元素。这里有一个例子:

To use this function, you have to give it a pointer to the first element of Xy. Here's an example:

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);

如果你不想流连与(*数组)[5000] [3000] 遍布code,因为固定的硬$ C的$ CD的尺寸,你当然可以在其他的答案使用的解决方案,但在时刻牢记指针之间的差异为指针,以浮动和彩车的二维数组。既然你似乎preFER这种方法,这里的code会是什么样子:

If you don't want to hang around with (*array)[5000][3000] all over the code because of the fixed hardcoded dimensions, you can certainly use the solutions in the other answers, but always keeping in mind the differences between a pointer to pointer to float and a 2D array of floats. Since you seem to prefer this approach, here's how the code would look like:

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()只接收的尺寸,并与分配的内存指针返回。我认为,在启动时使用浮动*** 来获得一点过于复杂。这是没有必要的。

I took the liberty to change your allocate_mem_m() to receive the dimensions only, and return the pointer with the allocated memory. I think it starts to get a little overly complex when you use float ***. That's not necessary.

作为一句忠告,我将同样添加 free_mem_m()来缓解释放分配内存的过程:

As a word of advice, I would equally add a free_mem_m() to ease the process of freeing the allocated memory:

void free_mem_m(int m, float **array) {
  int i;
  for (i = 0; i < m; i++) {
    free(array[i]);
  }
  free(array);
}

下面是完整的code房源的:

Here's the full code listing:

#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;
}

注意转()假定方阵(因为你分配 N 位置的块<$ C $ç> M 浮动)。如果你想用长方形矩阵利用这一点,你就必须分配 M 块持有 N 浮来代替。

Note that transpose() assumes a square matrix (because you allocate a block of n positions for m floats). If you want to use this with rectangular matrixes, you would have to allocate m blocks to hold n floats instead.

现场演示工作: http://ideone.com/CyNdpn

最后说明:对待一个二维数组作为一维数组是旧的,棘手的黑客攻击;它通常被认为是不好的做法(在我看来),你应该避免这种聪明code的。但是,如果你不想使用C99功能,这一切都是你留下了。

Final note: The hack to treat a 2D array as 1D array is old and tricky; it is generally considered bad practice (in my opinion), and you should avoid this kind of clever code. But if you don't want to use C99 features, this is all you're left with.

有关兴趣的读者,在作为一个有点垃圾邮件发送者的风险,我在我的博客写2篇文章对推广这个理念与N维任意阵列。它会在你为什么需要做技术解释有点深,如何做到这一点: HTTP: //codinghighway.com/?p=1159 http://codinghighway.com/?p= 1206

For interested readers, at the risk of being a bit of a spammer, I have written 2 articles in my blog about generalizing this idea to arbitrary arrays with N dimensions. It goes a little bit deeper in the technical explanation of why you need to do it, and how to do it: http://codinghighway.com/?p=1159 and http://codinghighway.com/?p=1206

这篇关于矩阵转置移植从Java到C,不兼容的类型问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆