簡體   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