0

固定サイズの配列を宣言しました:

int vals[25];

そして、valsの値を割り当てる関数に配列を送信したいと思います。

bool FetchValueArray(char* source, char* name, char* typeFormat, int count, void** destination)
{
    int i;
    char *t;
    t=strstr(source,name);
    if (t)
        if (destination != NULL)
        {
            for (i = 0;i < count;i++)
                sscanf(t,typeFormat,destination[i]);
                return true;
        }
    return false;
}

これは基本的に、特定の検索文字列の後にすべてを読み取ります。例えば:

FetchValueArray(source,"CONFIG=","%d",15,vals);

「CONFIG=」はプレーンテキストで、その後に15個のタブ区切りの数値が続きます。

ここには、間接参照配列と固定サイズの配列について悩むことにはほど遠いので、固定サイズの配列をパラメーターとしてvoid **として送信できるかどうかを知りたいです(サイズがアレイは尊重されます。別の問題です。)


tl;drバージョン

int vals[25];
bool foo(int size,void** d);
foo(25,vals);

なぜこれが許可されないのですか?

4

1 に答える 1

2

配列は最初の要素へのポインターに減衰し、任意の型へのポインターを暗黙的ににキャストできますvoid*。次に、配列アクセスが正しく機能するためには、FetchValueArray各配列要素の大きさを知る必要があります。void**へのポインタであるを渡そうとしているvoid*ので、配列アクセスは各要素をのサイズであるかのように扱いますがvoid*、これは間違っています。配列要素のサイズintは、必ずしも同じではありません。のサイズvoid*

だからvoid**間違っています。代わりにvoid*、「不明なタイプへのポインタ」を意味するを渡す必要があります。void*コンパイラは基になるpointed-to型のサイズを認識していないため、で配列インデックスを使用することはできません。あなたはそれを助ける必要があります。例えば:

bool FetchValueArray(char* source, char* name, char* typeFormat, int count, void* destination, size_t destElementSize)
{
    ...
    sscanf(t, typeFormat, (char*)destination + destElementSize * i);
    ...
}
...
FetchValueArray(source, "CONFIG=", "%d", 15, vals, sizeof(vals[0]));

ここでは、配列のインデックス作成を手動で実行しています。既知のポイントサイズ(1バイト)のvoid*toをキャストしてからchar*、要素ごとのサイズを掛けて配列オフセットを実行しています。結果は、適切なメモリ位置へのポインタです。これはsscanf期待どおりです。

ただし、ここでは十分に注意してください。デザインを再検討する必要があると思います。コンパイラは関数のセマンティクスを認識していないため、適切な引数を渡していることを確認できません。ここで気付かないうちに、偶発的なセキュリティの脆弱性を挿入するのは非常に簡単です。コンパイラーがより徹底的に検証できる別の設計を使用したほうがよいかどうかを考えてください。

于 2011-10-04T18:07:31.217 に答える