0

以下の関数は、構造体へのポインターの配列へのポインターを取り、API_AddParType各配列要素のフィールドの一部をリストします。次のように各要素にアクセスすると、すべてが期待どおりに機能し(*ppParams)[ii]ます。

void ParamsListWrapper::ListParams2(API_AddParType** ppParams)
{
    unsigned long ii, nParams;
    nParams = BMGetHandleSize( (GSHandle)ppParams ) / sizeof(API_AddParType);

    // list params
    for ( ii = 0; ii < nParams; ii++ ) {
        WriteReport( "Param name = \"%s\", double = %f", (*ppParams)[ii].name, (*ppParams)[ii].value.real );
    }
}

さて、次のような参照変数を使用しましょうAPI_AddParType& param

void ParamsListWrapper::ListParams1(API_AddParType** ppParams)
{
    unsigned long ii, nParams;
    nParams = BMGetHandleSize( (GSHandle)ppParams ) / sizeof(API_AddParType);

    // list params
    for ( ii = 0; ii < nParams; ii++ ) {
        API_AddParType& param = (*ppParams)[ii];
        WriteReport( "Param name = \"%s\", double = %f", param.name, param.value.real );
    }
}

へのポインターを使用して同じコードを試してみますAPI_AddParType

void ParamsListWrapper::ListParams3(API_AddParType** ppParams)
{
    unsigned long ii, nParams;
    nParams = BMGetHandleSize( (GSHandle)ppParams ) / sizeof(API_AddParType);

    // list params
    for ( ii = 0; ii < nParams; ii++ ) {
        API_AddParType* pParam = ppParams[ii];
        if (pParam != NULL) {
            WriteReport( "Param name = \"%s\", double = %f", pParam->name, pParam->value.real );
        } else {
            WriteReport( "Param is NULL" );
        }
    }
}

セグメンテーション違反が発生しました。どうしてですか?参照は問題なく機能するのに、ポインタでデータにアクセスすると失敗するのはなぜですか?

4

4 に答える 4

1

ラインを変えてみる

API_AddParType* pParam = ppParams[ii];

API_AddParType* pParam = (*ppParams) + ii;
于 2012-10-04T12:32:26.673 に答える
1

このように変更API_AddParType* pParam = ppParams[ii];API_AddParType* pParam = *ppParams;てアクセスしてみてください。pParam->namepParam[ii].name

アクセスする(*ppParams)[ii]ことで単一API_AddParTypeの を操作していますが、アクセスするpParam[ii]と の配列を操作していますAPI_AddParType

于 2012-10-04T12:24:52.003 に答える
1

最後のケースではppParams、配列へのポインターとしてではなく、ポインターの配列として扱っています。

ii配列の:th 要素は(*ppParams)[ii]、ポインターの場合とその他の場合の両方にあります。
あなたはそのアドレスを探しています。

API_AddParType* pParam = &(*ppParams)[ii];

また

API_AddParType* pParam = (*ppParams) + ii;
于 2012-10-04T14:05:09.640 に答える
1

API_AddParType以下の関数は、構造体へのポインタの配列へのポインタを取ります

void ParamsListWrapper::ListParams2(API_AddParType** ppParams)

関数の引数は、へのポインターAPI_AddParTypeの配列の最初の要素へのポインターである可能性がある、へのポインターへのポインターですAPI_AddParType

ppParams
   |
   v
pParam0|pParam1|pParam2|...
   |       |       |    ...
   v       v       v
  xyz     abc     mno   ...

または、へのポインター (の配列の最初の要素へのポインターAPI_AddParType)である可能性があります。

ppParams
   |
   v
 pParams
   |
   v
param0|param1|param2|...

ここで、匿名のメモリ位置に(paramsppParamsへのポインター) を指す名前を付けました。関数がそれ自体ではなくポインターを受け取る理由は、おそらくポインター自体が関数によって変更される可能性があるためです。pParamspParamspParamspParams

さて、最初のケースでは、つまり、などが指す(*ppParams)[ii] = pParam0[ii] = the object ii units after the start of xyzものを決して見ません(これらのポインターが、最初の要素が指す配列内を指すように設定されていない限り)。pParam1pParam2pParam1

2 番目のケースでは(*ppParams)[ii] = pParams[ii] = the object ii units after the start of param0、 、順番に整然と並べられたすべてのものを確認しparamNます。いいね。

API_AddParType* pParam = ppParams[ii]

最初の状況では、 、 、 、 ... を順番に見てxyzいきabcますmno

しかし、2 番目の状況でpParamは、 は の後のポインターii単位になりますpParamsが、それは へのポインターの配列の最初の要素ではないAPI_AddParTypeため、 へのアクセスppParams[ii]は未定義の動作ii > 0です。respへのアクセスのAPI_AddParTypeすぐ後ろへのポインタ。おそらくセグメンテーション違反を引き起こします。pParamspParam->namepParam->value.real

でセグメンテーション違反が発生したppParams[ii]が、 では発生しなかったという事実は、状況が実際には 2 番目であり、1 番目ではないことを(*ppParams)[ii]強く示唆しています。

于 2012-10-04T14:05:59.657 に答える