【问题标题】:Segmentation fault in passing matrix to C function将矩阵传递给 C 函数时出现分段错误
【发布时间】:2015-03-03 19:51:22
【问题描述】:

我无法弄清楚这段代码有什么问题(并且在之前的问答中找不到任何建议):

#include<stdio.h>

void fld(const int **b){
int i, j ;
printf("Hello R\n");
for (i=0; i<3; i++){
    for (j = 0; j<3; j++)
        printf("%d", b[i][j]);
    printf("\n");
    }
return;
}

int main(){
int i, j;
int b[3][3] = {
            {1,1,1},
            {1,2,1},
            {2,2,2}
            };

fld((void **)b);
system("pause");
return;
}

我尝试将矩阵传递给函数 fld 并打印出来,但它在运行代码时不断报告分段错误。

【问题讨论】:

  • 数组数组不是指向指针的指针。尝试在不使用 (void **) 强制转换的情况下传递数组 - 编译器会对你大喊
  • 我该如何纠正它?
  • @userXXX 首先不将数组视为指针。
  • 不要通过强制转换来强迫事情。
  • 你的 fld() 函数应该接受一个数组,或者你的数组应该被转换成一个指针数组。

标签: c segmentation-fault argument-passing


【解决方案1】:

这是一个在堆上动态分配内存的版本。它像main() 参数*argv[] 一样工作,即一个数组数组(尽管在这种情况下,行长度可能不同)。在这个答案中,您不需要传递 fld() 的数组大小来工作:但告诉它何时停止!原因是,它是一个数组指针的一维数组,每个指针也是一个一维数组。您也可以将相同的方法扩展到 3-D 数组。

#include <stdio.h>
#include <stdlib.h>

int **intarray(int rows, int cols) {
    int r;
    int **arr = malloc(rows*sizeof(int*));   // here an array of pointers
    if (arr == NULL)
         return NULL;
    for (r=0; r<rows; r++) {
        arr[r] = malloc(cols*sizeof(int));   // here an array of ints
        if (arr[r] == NULL)
             return NULL;
    }
    return arr;
}

void fld(const int **b, int rows, int cols){
    int i, j ;
    printf("Hello R\n");
    for (i=0; i<rows; i++){
        for (j = 0; j<cols; j++)
            printf("%-5d", b[i][j]);
        printf("\n");
        }
return;
}

int main(void) {
    int i, j;
    int **b = intarray(3, 3);
    if (b == NULL)
        return 0;
    for (i=0; i<3; i++)
        for (j=0; j<3; j++)
            b[i][j] = i*100 +j;
    fld(b, 3, 3);

    // free() the memory
    return 0;
}

程序输出

Hello R
0    1    2
100  101  102
200  201  202

【讨论】:

    【解决方案2】:
    void fld(const int b[][3]){
        int i, j;
        printf("Hello R\n");
        for (i=0; i<3; i++){
           for (j = 0; j<3; j++)
               printf("%d", b[i][j]);
           printf("\n");
        }
    return;
    }
    
    int main(int argc, char** argv) {
    
    int b[3][3] = {
            {1,1,1},
            {1,2,1},
            {2,2,2}
            };
    
    fld(b);
    return 0;
    };
    

    使用 g++ 编译和运行

    【讨论】:

    • 为什么不在第一个括号[]中定义边界?
    • 有可能。传递二维数组的问题是fld()不知道是2*4还是3*3还是4*2数组。这个答案显示了如何处理 - 编译器需要知道数组的每一行中有多少元素。然后,就像在 C 中一样,用户可以使用在界限内的行索引。
    • 谢谢,我明白了:所以在数组中,您有一个压缩的内存空间,需要将其划分为已知大小的数据块。将数组转换为 int ** 类型的指针确实有点帮助,但它没有传达有关这些整数如何划分为行的信息,这在尝试到达某个元素时真正重要。这也是为什么代码在 1D 中编译而不是在 2D 中编译的原因。
    • 同样,当某些数据存储在分配空间的指针数组中时(指针样式的指针),您不需要声明边界,因为很清楚 b[2][3] 表示检查“行”中的第二个指针(实际上是一维数组),(在数组方案中,问题是第二行从哪里开始......因为它全部压缩并且类型相同)然后使用该指针转到另一个内存地址和然后选择第三块整数大小的数据......(它也不关心是否有或没有过度读取某些数据)。
    • 换句话说:如果你有一个数组样式的数据集合 b[x][y] 意味着去 b+xcolumnsizeintsize+yintsize 位置(所以 colsize 很重要),在指针样式的格式中,这意味着检查 b+ptrsizex 处的地址,去那里检查 typesize*y 数据。
    猜你喜欢
    • 2014-12-10
    • 1970-01-01
    • 2015-06-12
    • 2023-03-08
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多