2

C でプログラムされた PIC からバイナリでレコードを受信しようとしています。

送信されるデータは次のように構造化されています。

typedef struct{int32 num1;
              float num2,num3,num4,num5;
              ...
              }RecordStructure;

typedef union{RecordStructure Record; char Array[48];} My_Rec_Structure;

私の質問はこれです:

最初の 4 バイト/文字は に属しint32 num1、次の 4 は に属しfloat num2ますか?

もしそうなら、送信に大きな問題があります。そうでない場合、データがどこにあるのかをどのように見分けることができますか?

4

4 に答える 4

3

はい、最初の部分ではありますが、注意が必要です。

C 標準では、最初の構造体メンバーを構造体の先頭に配置する必要があります。したがって、int32 は転送される最初の 4 バイトになります。ただし、PIC のバイト順序が異なる場合があるため、PIC から 0x12345678 を送信し、受信側で値 0x78563412 を読み取ることになります。

残りの構造体メンバーのアドレス指定に関しては、コンパイラーは各メンバー間に自由にパディングを追加できます。通常、これはメモリ アクセスを最適化するために行われることです。

PIC からテキスト出力を取得できる可能性がある場合は、stddef.h から offsetof() マクロを使用して、構造体メンバーのオフセットを取得できます。

fprintf(stderr, "num2 offset=%d\n", offsetof(RecordStructure, num2));
fprintf(stderr, "num3 offset=%d\n", offsetof(RecordStructure, num3));
于 2012-09-25T20:48:12.630 に答える
1

構造体内でデータを整列させる方法は、コンパイラーや特定の整列を強制するために使用されるプラグマによって異なります。

このコンパイラがアイテムをダブルワード境界に揃える場合、最初の4バイトnum1はchar配列の最初の4バイトと整列し、次の4バイトnum2はchar配列の次の4バイトと整列する必要があります。

可能であれば、デバッガーを使用して、データを受信したときにデータを調べることができます。また、送信されるデータには、特定の16進数のシーケンスを入れて、物事が思ったとおりに並んでいるかどうかを確認できるようにします。

したがって、PICでは、構造体で送信されるデータは次のようになります。

RecordStructure myRecord;
myRecord.num1 = 01F2E3D4C;
myRecord.num5 = myRecord.num4 = myRecord.num3 = myRecord.num2 = 0;

次に、それを送信して、どのように見えるかを確認します。num1の値が同じかどうか。

次に、たとえばmyRecord.num3 = 1.0の場合にデータを変更すると、物事が整列しているかどうかを確認できます。

于 2012-09-25T20:46:49.133 に答える
1

このは、PC (Linux/x86/gcc) と PIC(18F) の両方で ~RecordStructure~ の同じ定義を使用する方法を示しています。トリックは、#ifdef / #define両方のコンパイラをサポートするために使用することです。

#ifdef __cplusplus
# define __PACKED
# define __PACKED2 __attribute__((packed))
#else
# define __PACKED2
#endif


typedef struct __PACKED {
    opcodes_t opcode : 8;
    union {
        osci_config_t set_config_args;
        READ_SINGLE_ARGS read_single_args;
        SAMPLE_SINGLE_ARGS sample_single_args;
        SAMPLE_INTERLEAVED_ARGS sample_interleaved_args;
    } args;
} __PACKED2 opcode_decoder_t;
于 2012-09-25T21:03:39.347 に答える
1

はい。最初の 4 バイトは num1 に属し、次の 4 バイトは num2 に属します。ただし、int と float 内のバイト順序は、プラットフォームと実装に固有です。

ただし、これに影響を与える主なことが 2 つあります。1 つはアライメントで、もう 1 つはパディングです。変数間にメモリ ギャップが生じないように、パディングを 1 バイトに設定し、可能であればアライメントも 1 に設定してください。ただし、コンパイラとハードウェアによっては、アラインメントを 4 バイトまたは 8 バイトの倍数にする必要がある場合があります。この場合、いくつかのパディング変数を追加する必要があるかもしれません。MSVC では align キーワードを使用し、GCC ではアライメント属性を使用して、構造体/変数ごとのデフォルトのアライメントを変更できます。

__declspec(align(1)) //MSVC
__attribute__((aligned(1))) //GCC

例:

#pragma pack(1)
typedef struct{int32 num1;
              float num2,num3,num4,num5;
              ...
              }RecordStructure;

typedef union{RecordStructure Record; char Array[48];} My_Rec_Structure;
于 2012-09-25T20:51:59.223 に答える