繁体   English   中英

数组初始化器中多余元素的填充字节发现以及常见和特殊的编译器行为

[英]Padding bytes discovery & common and special compiler behavior on excess elements in array initializer

在我的项目中,我使用带char数组的结构的并集将字节插入不同的结构类型。

有一个数组保存特定结构的结构,以便知道接下来要使用哪种变量。

对于每种类型的结构,都会使用一个具有该结构类型的全局变量来找出填充字节的位置。 因此,所有成员都直接用0xFF .....初始化。 当函数插入字节时,将处理一个字段,它总是在数组中搜索不为0的下一个字节。并将该字节插入该位置。

用户可以从宏创建结构类型本身。 有时,数组的大小可能有所不同,并且还包含结构。 在普通的基本类型中,数组的第一个值也被初始化为0xFF,并且insert函数知道其最大长度,因此确定下一个值从何处开始是没有问题的。 但是,当有一个结构数组时,第一个初始值可以清楚地确定,但是第二个是一个问题,我不知道它从哪里开始。

由于该结构是嵌套的,因此开头也可能有填充字节。 因此,我需要初始化前两个值,以找出数组内部第一个结构的最后一个成员与第二个结构的第一个成员之间的距离。

在基本类型上,它类似于以下内容:

整数数组[2] = {2,2}

但是,如果数组是由用户定义的,则它也可能是:

int array [0] = {2,2}或int array [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开始之前可以有填充字节?

1)编译器行为:执行上述操作时,其他编译器会做什么? 仅显示警告并跳过不适合的值是常见的标准吗? 是否有编译器(也在考虑C ++编译器)引发错误并且没有进行编译或发生任何奇怪的事情?

int array[1]={2,2}

这是无效的声明。 要求编译器至少提出诊断,并有权停止编译。 与零元素数组的声明相同。

我现在发现了一种更好的方法,可以通过使用stddef.h中的offsetof宏来跳过结构中的填充字节并找到变量的位置,如果不可用,也可以自己定义。

    /* Offset of member MEMBER in a struct of type TYPE. */
    #define offsetof(TYPE, MEMBER)\
    ( (size_t) &( ( (TYPE *) 0 )->MEMBER ) )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM