gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 03:20:41 25 4
gpt4 key购买 nike

我需要编写一个函数,使用指针在 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,则只需删除使用 VLA 函数的代码。

    #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

关于c - 使用指针在 C 中复制多维数组时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46719124/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com