1

ここ数年、純粋な 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;

私はこれが本当にばかげた単純であることを知っていますが、私はこの単純なことを理解しようとして頭がいっぱいです。誰かが私を正しい方向に向けることができますか?

4

2 に答える 2

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*)datafloat*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ます。または、3 番目の可能性は、フラットな配列を渡して期待することです

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ます。

于 2012-12-06T18:42:09.107 に答える
1

2 次元配列はポインターへのポインターとして評価されないため、プロトタイプでは配列へのポインターの配列を使用する必要があります。

void print_data(float data[4][6]);
void print_data(float (*data)[6]);
于 2012-12-06T18:41:36.813 に答える