将打包结构成员的引用传递给模板。海湾合作委员会错误?

Passing reference of packed struct member to template. gcc bug?

我在将结构成员传递给模板函数时遇到问题。该函数的目标是获取成员的地址和大小。这是一个简单的例子:

这是结构体。具有packed属性。

struct TestStruct {
    unsigned char       elem1;
    unsigned char       elem2;
    uint64_t            elem3;
    char                buf[10000];
    int                 elem4;
    unsigned char       elem5;
}
__attribute__ ((packed));

这是模板函数,应该获取会员地址

template<typename T>
void addData(const T &val)
{
        printf ("address inside func: %p \n",&val);
}

int main(int argc, char *argv[])
{
        TestStruct testdata;
        testdata.elem4 = 0;
        printf ("struct address is:   %p \n",&testdata);
        printf ("elem4  address is:   %p \n",&testdata.elem4);
        addData(testdata.elem4);
        return 0;
}

问题:当属性((packed));已设置(如示例中所示) 模板函数接收到错误的成员地址:

输出:

struct address is:   0x7fff735bb4e0 
elem4  address is:   0x7fff735bdbfa 
address inside func: 0x7fff735bb4dc

如果我删除 "packed" 属性,一切正常。 没有错误也没有警告(即使使用 -Wall -Wextra),但没有将正确的地址传递给函数。

我读了这个:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566

并发现获取对压缩结构成员的引用时出现问题。 有趣的是,在我的模板函数中用 T& 替换 const T& 会产生错误消息:

error: cannot bind packed field ‘testdata.TestStruct::elem4’ to ‘int&’

所以,我有 2 个问题:

  1. 为什么压缩结构成员不能作为 const 引用传递,而它们的地址可以作为指针传递

  2. const T& 情况下发生了什么?没有错误,没有警告,但是传递给函数的地址不正确。我们知道,引用地址就是变量的地址,引用指向.

你的两个问题都在你发布的 link 中得到了回答。

1.为什么压缩结构成员不能作为常量引用传递,而它们的地址可以作为指针传递

Gabriel M. Beddingfield 在 his comment 中写道:

All assignments of obj.s to type short& and short* are incorrect, and ideally they would all result in compiler errors.

The C++ spec (C++03, Sects. 3.9, 3.9.1, 3.9.2) are very clear that T and "pointer to T" have implementation-specific alignment requirements. If you have a "pointer to T" then you may assume that it meets the alignment requirements. I'm sure the C spec has similar language.

我只能添加 C++14 标准中相应的引用 ([basic.align]/1):

Object types have alignment requirements (3.9.1, 3.9.2) which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type; stricter alignment can be requested using the alignment specifier

最重要的是,即使获取打包结构成员的地址也应该是错误的。

2。在 const T& 情况下会发生什么?没有错误,没有警告,但是传递给函数的地址不正确。我们知道,引用地址就是变量的地址,引用指向.

乔纳森·维克利 wrote:

A const-reference causes a temporary to be created, you didn't bind to the packed field


最重要的是,不能将非常量引用绑定到打包的结构字段本身并不是错误,错误是您可以同时获取它的地址。编译器应该允许或不允许两者。