多维数组作为函数参数的形式

多维数组作为函数参数的形式

     今天在看CSAPP的时候,直接敲入了书中的代码片段(P582),没有多加思考,却出现了段错误coredump,然后再纠结:被调用函数是否可以访问到主函数中的数据,函数中的自动变量存在栈中?最后才知道是函数声明的问题。所以通过这篇文章理清了数组作为参数时如何实践,同时不要忽略编译器给我们的警告。

在main中调用matvec1出现问题:
 $vi 2.c 
$ gcc 2.c csapp.o -lpthread
2.c: In function ‘main’:
2.c:49:2: warning: passing argument 1 of ‘matvec1’ from incompatible pointer type [enabled by default]
2.c:3:6: note: expected ‘int **’ but argument is of type ‘int (*)[3]’
$ ./a.out 
Segmentation fault (core dumped)
int *matvec1(int **A, int *x, int n){
    int i,j;
    int *y = Malloc(n * sizeof(int));

    for(i=0; i<n ;i++)
        y[i] = 0;

    for(i=0; i<n; i++)
        for(j=0; j<n; j++){
            y[i] += A[i][j] * x[j];
        }
    return y;
}


在一维数组作为函数参数时,既可以写成数组形式也可以写成指针形式,但是对于多维数组上述形式是错误的,只有第一维可以搞成指针形式,要特别注意。
可以选的形式有:
void func(int (*A)[10])
void func(int A[][10])
此时的程序可以正确执行。

int *matvec2(int A[][3], int *x, int n){
    int i,j;
    int *y = Malloc(n * sizeof(int));

    for(i=0; i<n ;i++)
        y[i] = 0;

    for(i=0; i<n; i++)
        for(j=0; j<n; j++){
            y[i] += A[i][j] * x[j];
        }
    return y;
}

int *matvec3(int (*A)[3], int *x, int n){
    int i,j;
    int *y = Malloc(n * sizeof(int));

    for(i=0; i<n ;i++)
        y[i] = 0;

    for(i=0; i<n; i++)
        for(j=0; j<n; j++){
            y[i] += A[i][j] * x[j];
        }
    return y;
}


但是,这样的情况就限制了这个函数只能处理的数组的类型,没有弹性,所以最优雅的做法是转为一维数组的逻辑来思考(理解行优先存储)。
func(&A[0][0][0], ....);
void func(int *p, int X, int Y, int Z){
  int i, j, k;
  // todo
  p[i*Y+j*Z+k] = AAA;
  //todo
}

所以修改后的用例如下:
int *matvec4(int *A, int *x, int n){
    int i,j;
    int *y = Malloc(n * sizeof(int));

    for(i=0; i<n ;i++)
        y[i] = 0;

    for(i=0; i<n; i++)
        for(j=0; j<n; j++){
            y[i] += A[i*n + j] * x[j];
        }
    return y;
}

int main(){
    int A[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
    int x[3] = {2,3,4};
    int i, n  = 3;

    int *y = NULL;
    //y = matvec3(A, x, n);
    y = matvec4(&A[0][0], x, 3);
    printf("Ax = [");
    for(i=0; i<n ;i++)
        printf("%d," , y[i]);
    printf("]\n");


    free(y);
    return 0;
}







郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。