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

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

     今天在看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;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值