C,传递2维数组

luk*_*ell 1 c

我现在几年没有使用纯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;
}
Run Code Online (Sandbox Code Playgroud)

上述程序将导致失败并引发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;
Run Code Online (Sandbox Code Playgroud)

我知道这真的很愚蠢,但是我正试着弄清楚这个简单的事情.有人能指出我正确的方向吗?

Dan*_*her 9

void print_data(float **data, int I, int J)
Run Code Online (Sandbox Code Playgroud)

期望一个指针数组(数组的第一个元素)float.

但是当你通过

float data[4][6];
Run Code Online (Sandbox Code Playgroud)

你传递一个指针float[6].

所以在print_data,访问

data[i]
Run Code Online (Sandbox Code Playgroud)

sizeof(float*)i * sizeof(float*)地址data保持之后以字节偏移量读取字节,并将这些字节解释为float*然后解除引用(在添加合适的偏移量之后)data[i][j].

因此,当您传递2D数组时,某些float值将被解释为指针,然后进行跟踪.这通常会导致分段错误.

你可以申报

void print_data(float (*data)[6], int I, int J)
Run Code Online (Sandbox Code Playgroud)

并传递你的2D数组,或者你需要传递一个指针数组,

float *rows[4];
for(i = 0; i < 4; ++i) {
    rows[i] = &data[i][0];
}
Run Code Online (Sandbox Code Playgroud)

并通过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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并通过&data[0][0]main.