我现在几年没有使用纯C了,但我似乎无法使这个真正基本的用例工作。以下是简单C中的简单用例,实际情况包含在HDF库中,但我需要先从此开始。
#include <stdio.h>
void print_data(float **data, int I, int J)
{
for(int i=0;i<I;i++)
{
for(int j=0;j<J;j++)
printf("%02.2f\t", data[i][j]);
printf("\n");
}
}
void initialize_data(float **data, int I, int J)
{
for(int i=0;i<I;i++)
for(int j=0;j<J;j++)
data[i][j] = i * 6 + j + 1;
}
int main(int argc, char *argv[])
{
float data[4][6];
int I=4;
int J=6;
initialize_data((float **)data, 4,6);
print_data((float **)data, 4, 6);
return 0;
}
上述程序将导致失败并引发EXC_BAD_ACCESS信号。 GDB输出:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5fc0131a
0x0000000100000de6 in initialize_data (data=0x7fff5fbff348, I=4, J=6) at simple.c:16
16 data[i][j] = i * 6 + j + 1;
我知道这真的很愚蠢,但是我正试着弄清楚这个简单的事情。有人能指出我正确的方向吗?
答案 0 :(得分:9)
void print_data(float **data, int I, int J)
需要一个指针数组(float
的数组的第一个元素。
但是当你通过时
float data[4][6];
您将指针传递给float[6]
。
所以在print_data
中,访问
data[i]
在地址sizeof(float*)
成立后的i * sizeof(float*)
字节偏移处读取data
个字节,并将这些字节解释为float*
,然后解除引用(添加合适的地址后) data[i][j]
中的偏移量。
因此,当您传递2D数组时,某些float
值将被解释为指针然后被跟随。这通常会导致分段错误。
您可以声明
void print_data(float (*data)[6], int I, int J)
并传递你的2D数组,或者你需要传递一个指针数组,
float *rows[4];
for(i = 0; i < 4; ++i) {
rows[i] = &data[i][0];
}
并传递rows
。或者,第三种可能性是通过并期望一个平面阵列
void initialize_data(float* data, int I, int J) {
for(i = 0; i < I; ++i) {
for(j = 0; j < J; ++j) {
data[i*J + j] = whatever;
}
}
}
并从&data[0][0]
传递main
。
答案 1 :(得分:1)
不会将二维数组计算为指向指针的指针,因此您需要在原型中使用指向数组的指针数组:
void print_data(float data[4][6]);
void print_data(float (*data)[6]);