将打包结构成员的引用传递给模板。gcc 错误?

Nuc*_*ear 6 c++ struct reference

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

这是结构。它具有打包属性。

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

这是模板函数,它应该获取成员的地址

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;
}
Run Code Online (Sandbox Code Playgroud)

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

输出:

struct address is:   0x7fff735bb4e0 
elem4  address is:   0x7fff735bdbfa 
address inside func: 0x7fff735bb4dc
Run Code Online (Sandbox Code Playgroud)

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

我读到这个:

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

并发现有一个问题,获取对packed-struct 成员的引用。有趣的是,在我的模板函数中用 T& 替换 const T& 会产生错误消息:

error: cannot bind packed field ‘testdata.TestStruct::elem4’ to ‘int&’
Run Code Online (Sandbox Code Playgroud)

所以,我有两个问题:

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

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

Ant*_*vin 5

您的两个问题都在您发布的链接中得到了解答。

1.为什么不能将packed-struct成员作为const引用传递,而它们的地址可以作为指针传递

Gabriel M. Beddingfield 在他的评论中写道:

obj.s 对 short& 和 short* 类型的所有赋值都是不正确的,理想情况下它们都会导致编译器错误。

C++ 规范(C++03,第 3.9、3.9.1、3.9.2 节)非常清楚 T 和“指向 T 的指针”具有特定于实现的对齐要求。如果您有一个“指向 T 的指针”,那么您可以假设它满足对齐要求。我确信 C 规范有类似的语言。

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

对象类型具有对齐要求(3.9.1、3.9.2),这对可以分配该类型对象的地址进行了限制。的对准是表示在一个给定的对象可以被分配连续地址之间的字节数实现定义整数值。对象类型对该类型的每个对象强加了对齐要求;可以使用对齐说明符请求更严格的对齐

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

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

乔纳森·韦克利写道

常量引用会导致创建临时对象,您没有绑定到打包字段


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