2

XC32 コンパイラを使用して PIC32MX795F512L のコードを作成しています。void* として関数に渡されたバッファーからデータを読み取る必要があります。データを符号なし 32 ビット整数の配列として読み取る必要があります。問題は、void* を uint32* にキャストし、その配列のインデックス 0 の値を読み取ろうとすると、プロセッサによって一般的なエラー ハンドラーが呼び出されますが、void* を uint8* にキャストしていくつかの処理を行う場合です。ビット操作で同じデータを取得すると、正常に動作します。

コードは次のようになります。

void foo(void* data, uint32 length)
{
    uint32 i,j;
    uint32 block;
    for(i = 0, j = 0; i < length; i+= sizeof(uint32),j++)
    {
        printfUART(DEBUG_UART,"Debug 0\r\n");
#if 0//working code
        block = ((uint8*)data)[i + 3];
        block <<= 8;
        block |= ((uint8*)data)[i + 2];
        block <<= 8;
        block |= ((uint8*)data)[i + 1];
        block <<= 8;
        block |= ((uint8*)data)[i + 0];
#else//not working code
        block = ((uint32*)data)[j];
#endif
        printfUART(DEBUG_UART,"Debug 1\r\n");
    }
}

コードを変更する#if 0と、期待どおりに機能し、ループ内で何度も表示および出力されます。#if 1"Debug 0""Debug 1"

しかし、そのままにしておくと、"Debug 0" が 1 回だけ出力され、コードはループから飛び出して、コンパイラによって設定された cpu の一般的なエラー ハンドラにジャンプします。これは XC32 ompiler のバグですか、それとも不足していますか?

4

4 に答える 4

5

これはアライメントの問題だと思います。

が偶数アドレスでない場合data(たとえば、実際にはバイトの配列であるため)、プラットフォームで 32 ビット単位でアクセスできない可能性があります。

C 標準 (ISO/IEC 9899:1999、6.3.2.3) は次のように述べています。

オブジェクトまたは不完全な型へのポインターは、別のオブジェクトまたは不完全な型へのポインターに変換される場合があります。結果のポインターがポイント先の型に対して正しく配置されていない場合、動作は未定義です。

于 2014-07-02T14:46:40.747 に答える
2

アラインメントの問題が発生する代わりにblock = ((uint32*)data)[j];、次の方法で意図した効果を得ることができます。

memcpy( &block, data + j, sizeof block );

これは、個々のバイトから構築するバージョンとは概念的に異なることに注意してください。CPU が整数を表現する方法 (一般に「エンディアン」と呼ばれます) によって異なります。

于 2014-07-04T00:21:06.443 に答える