私のプロジェクトでは、構造体と 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 が始まる前にパディング バイトがありますか?