繁体   English   中英

使用指针在C中复制多维数组时出现分段错误

[英]Segmentation fault when copy a multidimensional array in C using pointers

我需要编写一个函数,它将使用指针在C中复制多维数组。 我在Gentoo上使用gcc 5.4.0和clang 3.9.1。 我使用的事实是使用数组名称与引用第一个元素的引用相同,所以如果我们有二维数组,则array_2d = &array_2d[0]*array_2d = *(&array_2d[0]) = array_2d[0] 这是我的代码:

#include <stdio.h>
#define ROWS 2
#define COLS 3

void copy_ptr(double *src, double *dest, int len);
void copy_ptr2d(double **src, double **dest, int rows, int cols);

int main() {
    double array[ROWS][COLS] = { { 12.3, 55.1 }, { 33.6, 21.9, 90.8 } };
    double array2[ROWS][COLS];
    printf("Array { { 12.3, 55.1 }, { 33.6, 21.9, 90.8 } }\n");
    printf("Array copy:\n");
    copy_ptr2d(array, array2, ROWS, COLS);
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("array2[%d][%d]: %lf\n", i, j, array2[i][j]);
        }
        printf("\n");
    }
    return 0;
}

void copy_ptr2d(double **src, double **dest, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        copy_ptr(*src, *dest, cols);
        src++;
        dest++;
    }
}

void copy_ptr(double *src, double *dest, int len) {
    for (int i = 0; i < len; i++) {
        *dest = *src;
        dest++;
        src++;
    }
}

gcc 5.4.0下编译代码的结果:

pecan@tux ~ $ gcc main.c 
main.c: In function ‘main’:
main.c:13:16: warning: passing argument 1 of ‘copy_ptr2d’ from incompatible pointer type [-Wincompatible-pointer-types]
     copy_ptr2d(array, array2, ROWS, COLS);
                ^
main.c:6:6: note: expected ‘double **’ but argument is of type ‘double (*)[3]’
 void copy_ptr2d(double **src, double **dest, int rows, int cols);
      ^
main.c:13:23: warning: passing argument 2 of ‘copy_ptr2d’ from incompatible pointer type [-Wincompatible-pointer-types]
     copy_ptr2d(array, array2, ROWS, COLS);
                       ^
main.c:6:6: note: expected ‘double **’ but argument is of type ‘double (*)[3]’
 void copy_ptr2d(double **src, double **dest, int rows, int cols);
      ^
pecan@tux ~ $ ./a.out 
Array { { 12.3, 55.1 }, { 33.6, 21.9, 90.8 } }
Array copy:
Segmentation fault

根据clang 3.9.1:

pecan@tux ~ $ clang main.c 
main.c:13:16: warning: incompatible pointer types passing 'double [2][3]' to parameter of type 'double **' [-Wincompatible-pointer-types]
    copy_ptr2d(array, array2, ROWS, COLS);
               ^~~~~
main.c:6:26: note: passing argument to parameter 'src' here
void copy_ptr2d(double **src, double **dest, int rows, int cols);
                         ^
main.c:13:23: warning: incompatible pointer types passing 'double [2][3]' to parameter of type 'double **' [-Wincompatible-pointer-types]
    copy_ptr2d(array, array2, ROWS, COLS);
                      ^~~~~~
main.c:6:40: note: passing argument to parameter 'dest' here
void copy_ptr2d(double **src, double **dest, int rows, int cols);
                                       ^
2 warnings generated.
pecan@tux ~ $ ./a.out 
Array { { 12.3, 55.1 }, { 33.6, 21.9, 90.8 } }
Array copy:
Segmentation fault

我不知道为什么我有内存泄漏和我做错了我得到的“分段错误”。 谁能帮我?

正如您所提到的,在具有罕见异常的表达式中使用的数组指示符将转换为指向其第一个元素的指针。

所以如果你有一个声明的数组

#define ROWS 2
#define COLS 3

//...

double array[ROWS][COLS];

然后作为参数传递给函数,例如

f( array );

它被转换为指向其第一个元素的指针。

那个数组的元素有什么类型?

它的类型为double[COLS] 那是二维数组的元素是一维数组。

因此,指向double[COLS]类型数组的指针将具有double ( * )[COLS]

因此相应的函数参数应具有相同的类型。

您可以将函数参数声明为可变长度数组(VLA)或具有已知固定大小的数组。

这是一个使用两种方法的示范程序。

这个函数声明

    void copy_ptr2d( size_t, size_t, double [][*], double [][*] );

使用(指向)可变长度数组作为参数,

这个函数声明

    void copy_ptr2d2( double [][COLS], double [][COLS], size_t );

在编译时使用(指针)具有已知大小COLS的数组作为参数。

如果您的编译器不支持VLA,那么只需删除使用VGA功能的代码。

    #include <stdio.h>

    #define ROWS 2
    #define COLS 3

    void copy_ptr2d( size_t, size_t, double [][*], double [][*] );

    void copy_ptr2d2( double [][COLS], double [][COLS], size_t );

    void copy_ptr( double *, double *, size_t );

    int main( void ) 
    {
        double array[ROWS][COLS] = 
        { 
            { 12.3, 55.1 }, 
            { 33.6, 21.9, 90.8 } 
        };

        double array2[ROWS][COLS];

        puts( "array\n=====" );

        for ( size_t i = 0; i < ROWS; i++ )
        {
            for ( size_t j = 0; j < COLS; j++ ) printf( "%4.1f ", array[i][j] );
            putchar( '\n' );
        }

        putchar( '\n' );

        puts( "Array copying...\n" );

        copy_ptr2d( ROWS, COLS, array, array2 );

        puts( "array2\n======" );

        for ( size_t i = 0; i < ROWS; i++ )
        {
            for ( size_t j = 0; j < COLS; j++ ) printf( "%4.1f ", array2[i][j] );
            putchar( '\n' );
        }

        putchar( '\n' );

        puts( "Array copying...\n" );

        copy_ptr2d2( array, array2, ROWS );

        puts( "array2\n======" );

        for ( size_t i = 0; i < ROWS; i++ )
        {
            for ( size_t j = 0; j < COLS; j++ ) printf( "%4.1f ", array2[i][j] );
            putchar( '\n' );
        }

        putchar( '\n' );

        return 0;
    }

    void copy_ptr2d( size_t rows, size_t cols, double src[][cols], double dest[][cols] )
    {
        for ( size_t i = 0; i < rows; i++ )
        {
            copy_ptr( src[i], dest[i], cols );
        }
    }    

    void copy_ptr2d2( double src[][COLS], double dest[][COLS], size_t rows )
    {
        for ( size_t i = 0; i < rows; i++ )
        {
            copy_ptr( src[i], dest[i], COLS );
        }
    }    

    void copy_ptr( double *src, double *dest, size_t len ) 
    {
        while ( len-- ) *dest++ = *src++;
    }

程序输出看起来像

array
=====
12.3 55.1  0.0 
33.6 21.9 90.8 

Array copying...

array2
======
12.3 55.1  0.0 
33.6 21.9 90.8 

Array copying...

array2
======
12.3 55.1  0.0 
33.6 21.9 90.8 

尝试这样的事情:

#include <stdio.h>
#define ROWS 2
#define COLS 3

void copy_ptr(double src[], double dest[], int len);
void copy_ptr2d(double src[ROWS][COLS], double dest[ROWS][COLS], int rows, int cols);

int main() {
    double array[ROWS][COLS] = { { 12.3, 55.1 }, { 33.6, 21.9, 90.8 } };
    double array2[ROWS][COLS];
    printf("Array { { 12.3, 55.1 }, { 33.6, 21.9, 90.8 } }\n");
    printf("Array copy:\n");
    copy_ptr2d(array, array2, ROWS, COLS);
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("array2[%d][%d]: %lf\n", i, j, array2[i][j]);
        }
        printf("\n");
    }
    return 0;
}

void copy_ptr2d(double src[ROWS][COLS], double dest[ROWS][COLS], int rows, int cols)
{
    for (int i = 0; i < rows; i++) {
        copy_ptr(*src, *dest, cols);
        src++;
        dest++;
    }
}

void copy_ptr(double src[], double dest[], int len)
{
    for (int i = 0; i < len; i++) {
        *dest = *src;
        dest++;
        src++;
    }
}

你明白这是怎么回事吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM