0

私のプロジェクトでは、構造体と char 配列の共用体を使用して、異なる構造体型にバイトを挿入しています。

次に来る変数の種類を知るために、特定の構造体の構造を保持する配列があります。

その構造体の種類ごとに、その構造体の型を持つ 1 つのグローバル変数を使用して、パディング バイトがどこにあるかを調べます。そのため、すべてのメンバーは 0xFF..... で直接初期化されます。バイトを挿入する関数がフィールドを処理するとき、0 ではない配列内の次のバイトを常に検索します。そして、その位置にバイトを挿入します。

構造体型自体は、マクロからユーザーが作成できます。場合によっては、配列のサイズが異なり、構造体も含まれる場合があります。通常の基本型では、配列の最初の値も 0xFF に初期化され、挿入関数はその最大長を認識しているため、次の値の開始位置を決定することは問題ありません。しかし、構造体配列がある場合、最初の初期値は明確に識別できますが、2 番目の初期値は問題であり、どこから始まるのかわかりません。

構造体がネストされているため、先頭にパディング バイトが含まれる場合もあります。したがって、配列内の最初の構造体の最後のメンバーと 2 番目の構造体の最初のメンバーの間の距離を調べるために、最初の 2 つの値を初期化する必要があります。

基本的なタイプでは、これは次のようになります。

int 配列[2]={2,2}

ただし、配列がユーザーによって定義されている場合は、次のようにもなります。

int 配列[0]={2,2} または int 配列[1]={2,2}

GCC はそれに対する警告を作成し、配列の使用可能な部分を埋めるだけです。

今、私は次の質問があります:

1) コンパイラの動作: 上記のことを行うと、他のコンパイラは何をしますか? 警告のみを表示し、収まらない値をスキップするのが一般的な標準ですか? エラーを発生させ、コンパイルしない、または何かおかしなことをするコンパイラ (C++ コンパイラも考慮) はありますか?

2) パディングバイトを見つける他の可能性を知っていますか?

コードでの例:

rosc_buildup_t rosc_static_msg_buildup_array_a_test_pkg__gnampf[]=
{
ROS_MSG_BUILDUP_TYPE_ARRAY,
    ROS_MSG_BUILDUP_TYPE_STRING,

ROS_MSG_BUILDUP_TYPE_MESSAGE_END,
}

#define ROSC_USERDEF_STATIC_MSG_a_test_pkg__gnampf(\
USER_TYPE,\
MAX_SIZE_STRING_fest)\
typedef \
struct  /*Main Message Start*/\
{\
struct  /*fest*/\
{\
    uint32_t size;\
    struct  /*fest array data*/\
    {\
        uint32_t size;\
        bool oversize;\
        char str_data[MAX_SIZE_STRING_fest];\
    }data[4];\
}fest;\
}\
uint32_t rosc_static_msg_length_definition__a_test_pkg__gnampf__ ## USER_TYPE[]={\
4,\
MAX_SIZE_STRING_fest};\
union\
{\
const rosc_static_msg__a_test_pkg__gnampf__ ## USER_TYPE msg;\
const char padding_out[ sizeof( rosc_static_msg__a_test_pkg__gnampf__ ##     USER_TYPE     )];\
}rosc_static_msg_lookup__a_test_pkg__gnampf__ ## USER_TYPE ={{ 0xFFFFFFFF, {{     0xFFFFFFFF,0xFF, {0xFF} }} }};

アップデート(1)

3) 次のように、別の構造体の中に構造体がある場合:

struct
{
   uint8_t foo;
   ... whatever...
   struct
   {
     uint8_t foo1;
     uint16_t foo2;
     uint8_t foo3;
   }b[3];
 }a;

foo1 は常に先頭にありますか、それとも foo1 が始まる前にパディング バイトがありますか?

4

2 に答える 2

1

1) コンパイラの動作: 上記のことを行うと、他のコンパイラは何をしますか? 警告のみを表示し、収まらない値をスキップするのが一般的な標準ですか? エラーを発生させ、コンパイルしない、または何かおかしなことをするコンパイラ (C++ コンパイラも考慮) はありますか?

int array[1]={2,2}

これは無効な宣言です。コンパイラは、少なくとも診断を発生させる必要があり、コンパイルを停止する権限があります。ゼロ要素の配列の宣言についても同じです。

于 2013-06-27T22:14:05.523 に答える
0

構造体のパディング バイトをスキップし、stddef.h 内の offsetof マクロを使用して変数の位置を見つけるより良い方法を見つけました。これが利用できない場合は、自分で定義することもできます。

    /* Offset of member MEMBER in a struct of type TYPE. */
    #define offsetof(TYPE, MEMBER)\
    ( (size_t) &( ( (TYPE *) 0 )->MEMBER ) )
于 2013-07-09T13:03:44.847 に答える