我可以通过将(c,a,b)
传递给add_mat
函数来实现这一点,其中a,b
的结果存储在c
中,
void add_mat(int c[][3], int a[][3], int b[][3], int m, int n)
如果我想以这种方式构建功能,那么add_mat
的返回类型应该是什么
?? add_mat(int a[][3], int b[][3], int m, int n)
以下是示例代码
#include<stdio.h>
void read_mat(int a[][3], int m, int n){
//scan data
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
printf("[%d][%d] : ",i,j);
a[i][j]=i+j;
}
}
}
int* add_mat(int a[][3], int b[][3], int m, int n){
int c[3][3];
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
return c;
}
int main(){
int a[3][3];
int m=2,n=2; //mxn of a matrix
read_mat(a, m, n);
//add
int b[3][3];
read_mat(b, m, n);
int* c[3][3];
c = add_mat(a,b,m,n);
return 0;
}
就像将c
函数中的计算值add_mat
传递或指向main
函数中的变量一样。
答案 0 :(得分:2)
你不能这样做,因为当函数终止时c
矩阵的记忆将消失。
您需要使用malloc()
动态分配它,以便内存不会被释放,除非您调用free()
。如果你想看一下,我在2D dynamic array (C)中有一些例子。
使用上一个函数,您可以在函数外部创建矩阵c
(在main()
中),这就是不需要动态内存分配的原因。
PS:您应该在启用警告的情况下进行编译:
prog.c: In function 'add_mat':
prog.c:19:12: warning: returning 'int (*)[3]' from a function with incompatible return type 'int *' [-Wincompatible-pointer-types]
return c;
^
prog.c:19:12: warning: function returns address of local variable [-Wreturn-local-addr]
prog.c: In function 'main':
prog.c:32:7: error: assignment to expression with array type
c = add_mat(a,b,m,n);
^
prog.c:31:10: warning: variable 'c' set but not used [-Wunused-but-set-variable]
int* c[3][3];
^
这是一个工作示例,仅用于演示目的:
#include <stdio.h>
#include <stdlib.h>
void read_mat(int a[][2], int n, int m){
//scan data
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
a[i][j] = i + j ;
}
}
}
int **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i, **table;
table = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(int) );
return table;
}
void print(int** p, int N, int M) {
int i, j;
for(i = 0 ; i < N ; i++)
for(j = 0 ; j < M ; j++)
printf("array[%d][%d] = %d\n", i, j, p[i][j]);
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int** add_mat(int a[][2], int b[][2], int m, int n){
int** c = get(n, m);
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
return c;
}
int main(){
int n = 2, m = 2; //nxm of a matrix
int a[n][m];
read_mat(a, n, m);
//add
int b[n][m];
read_mat(b, n, m);
int** c;
c = add_mat(a, b, n, m);
print(c, n, m);
free2Darray(c ,n);
return 0;
}
输出:
array[0][0] = 0
array[0][1] = 2
array[1][0] = 2
array[1][1] = 4
PPS:如果你真的想使用静态数组,那么我建议使用int c[3][3]; add_mat(c, a, b, m, n);
答案 1 :(得分:1)
哦,是的,指针......
在C语言中,本地声明的数组通常在堆栈上分配(而不是在堆上),这意味着它们在相应的范围之外无效。
换句话说,在函数add_mat()
中,技术上可以返回c
,但只要函数执行,它指向的地址只包含有意义的矩阵数据。
从函数返回后,函数的返回值是一个指针,它仍然包含(指向)地址,其中矩阵在执行函数期间存储 ,但该位置的内容,即矩阵数据,现在可以包含任意垃圾。
所以你在做什么在技术上是可行的(即不会抛出编译错误),但绝对不是你想要的。
其次,您的行int* c[3][3];
可能不是您想要的那样。您在这里声明c
是指向int 的指针的二维数组(矩阵)。这是不正确的,因为您要处理int
值,而不是指针到int
值(地址)。
要解决这两个问题,只需编写int c[3][3];
而不是int* c[3][3];
,然后按如下方式更改add_mat()
函数:
void add_mat(int a[][3], int b[][3], int c[][3], int m, int n){
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
}
然后调用那个函数:
add_mat(a,b,c,m,n);
答案 2 :(得分:1)
在您的代码中add_mat
返回指向仅在函数执行时存在的变量的指针。您可以使用动态分配的矩阵来实现目标。
在C中,通常通过指针将指向矩阵行的指针作为第一个参数传递动态分配的矩阵:
void foo(int** matrix, size_t m, size_t n);
这里matrix
是指向指针数组的指针。此数组中的每个指针都指向矩阵行。因此,matrix[0]
指向包含矩阵第一行的数组。
对于任何大小的数组,通常使用size_t
类型。
如果需要动态创建矩阵,请注意内存。应释放每个动态分配的块。否则,您将获得内存泄漏,这可能会导致程序崩溃。因此,在分配矩阵行时,应检查当前行的分配是否成功。如果没有,您应该释放以前分配的所有行。
您的问题有一个可用的代码:
#include <stdio.h>
#include <stddef.h>
#include <malloc.h>
void free_mat(int** a, size_t m) {
if (!a) {
return;
}
for (size_t i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
int** create_mat(size_t m, size_t n) {
int** rows = calloc(m, sizeof(int*));
if (!rows) {
return NULL;
}
for (size_t i = 0; i < m; i++) {
rows[i] = malloc(n * sizeof(int));
if (!rows[i]) {
free_mat(rows, m);
return NULL;
}
}
return rows;
}
void read_mat(int** a, size_t m, size_t n) {
for (size_t i = 0; i < m; i++) {
for (size_t j = 0; j < n; j++) {
printf("[%d][%d]: ", i, j);
scanf("%d", a[i] + j);
}
}
}
void print_mat(const int* const* a, size_t m, size_t n) {
for (size_t i = 0; i < m; ++i) {
for (size_t j = 0; j < n; ++j) {
printf("[%d][%d]: %d\n", i, j, a[i][j]);
}
}
}
int** add_mat(const int* const* a, const int* const* b, size_t m, size_t n) {
int** c = create_mat(m, n);
if (c) {
for (size_t i = 0; i < m; ++i) {
for (size_t j = 0; j < n; ++j) {
c[i][j] = a[i][j] + b[i][j];
}
}
}
return c;
}
int main() {
size_t m = 3;
size_t n = 3;
int** a = create_mat(m, n);
int** b = create_mat(m, n);
if (!a || !b) {
printf("error when allocating matrix\n");
}
else {
read_mat(a, m, n);
read_mat(b, m, n);
int** c = add_mat(a, b, m, n);
if (!c) {
printf("error when allocating matrix\n");
}
else {
print_mat(c, m, n);
free_mat(c, m);
}
}
free_mat(a, m);
free_mat(b, m);
return 0;
}
但如果add_mat
没有创建新矩阵,那么你会更灵活。
通常将指向结果矩阵的指针作为函数参数传递:
void add_mat(int** c, const int* const* a, const int* const* b, size_t m, size_t n);