1

私は機能を持っています:

uint8_t*  createTestBuffer()
{

    uint8_t buffer[] = {5,7,3,4,1,9,3};
    return &buffer;
}

それを実行する:

uint8_t *buff = createTestBuffer();

コンパイラ エラーを返します。

c_programming.c:11:9: warning: incompatible pointer types returning 'uint8_t (*)[7]' from a function with result type
      'uint8_t *' (aka 'unsigned char *') [-Wincompatible-pointer-types]
        return &buffer;

関数から uint8_t の配列へのポインターを返します。ここで何が間違っているのですか?

4

3 に答える 3

8

コンパイラはreturn &buffer;、 が 7 の配列uint8_t(綴りはuint8_t (*)[7]) へのポインターを返すことを伝えましたが、関数が を返すと言いましたがuint8_t *、これらは異なり、互換性のないポインター型です。

と書いた場合return buffer;、型は正しくなりますが、コードは依然として間違っています。スタック上にあるローカル配列へのポインターを安全に返すことはできません。

それを作成してstatic const uint8_t buffer[] = { … };、関数の戻り値の型を に変更し、const uint8_t *それに応じて使用します (データが変更されないため、スレッドセーフです)。

const uint8_t *createTestBuffer(void)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    return buffer;
}

または、次のような形式で動的割り当てを使用します。

uint8_t *createTestBuffer(void)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    uint8_t *rv = malloc(sizeof(buffer));
    if (rv != 0)
        memmove(rv, buffer, sizeof(buffer));
    return rv;
}

ここでの呼び出しコードは、null 以外のポインターを再度取得することを確認する必要があることに注意してください。また、free()null でない限り (呼び出しがオプションになる場合)、返されたポインターで確実に呼び出す必要があることに注意してくださいfree()

または、呼び出し元にバッファーを渡すようにします。ユーザーが十分なスペースを渡すことを知っていると仮定して、危険な生活を送っています。

void createTestBuffer(uint8_t *output)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    memmove(output, buffer, sizeof(buffer));
}

または、危険の少ない生活:

static inline size_t min(size_t a, size_t b) { return (a < b) ? a : b; }

void createTestBuffer(uint8_t *output, size_t outlen)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    memmove(output, buffer, min(sizeof(buffer), outlen));
}

「コピーされたバッファよりも小さい出力バッファ」を処理する方法は他にもあります。このコードは安全な範囲でコピーされましたが、切り捨てを示す 0 または 1 のステータスを返したり、指定された長さが必要な長さよりも小さくないことを表明したり、または …</p>

于 2014-05-11T20:24:02.477 に答える
1

ここに 2 つのエラーがあります。

最初のエラーは、変数のアドレスへのポインターを与える&演算子 (別名アドレス of )を使用してバッファーを返していることです。エラーが伝えているように、配列はすでにuint8_t*返されています。uint8_t(*)[7]そして、関数が前者を返すのに対し、コンパイラはそれを返そうとしているので、不機嫌です。

ただし、@TimCooper によって最初に発見されたように、実際にはコードにさらに重要なエラーがあることを知っておいてください。

関数のスコープ内で変数を割り当てていて、その関数の外で使用したい場合。C では、関数内で変数を宣言すると、割り当てに使用されたメモリがその関数の終了時に解放されるため、関数の型を修正しても期待どおりに動作しません。

関数の外部で uint8_t 配列を宣言し、それをパラメーターとして関数に渡す必要があります。

uint8_t* createTestBuffer(uint8_t* array) {
    array[0] = 5;
    array[1] = 7;
    array[2] = 3;
    array[3] = 4;
    array[4] = 1;
    array[5] = 9;
    array[6] = 3;
    return array;
}

または、malloc を使用して、メモリをスタックではなくヒープに割り当てる必要があります。

uint8_t* createTestBuffer() {
    uint8_t* array = , malloc(sizeof(uint8_t)*7);
    array[0] = 5;
    array[1] = 7;
    array[2] = 3;
    array[3] = 4;
    array[4] = 1;
    array[5] = 9;
    array[6] = 3;
    return array;
}

free()ただし、使い終わったら、バッファ変数を忘れないようにする必要があります。

于 2014-05-11T20:22:19.537 に答える