正在将压缩结构成员的引用传递给模板.gcc错误

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

本文关键字:错误 gcc 引用 压缩 结构 成员      更新时间:2023-10-16

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

这就是结构。它具有压缩属性。

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&与T&在我的模板函数中,生成错误消息:

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

所以,我有两个问题:

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

  2. 常数T&案例没有错误,也没有警告,但是错误的地址被传递给了函数。正如我们所知,引用的地址是变量的地址,引用指向.

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

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

Gabriel M.Beddingfield在评论中写道:

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

C++规范(C++03,第3.9、3.9.1、3.9.2节)非常清楚;指向T"的指针;具有实施特定的对齐要求。如果你有一个";指向T"的指针;那么您可能会认为它符合对齐要求。我相信C规范也有类似的语言。

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

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

它的底线是,即使获取压缩结构成员的地址也应该是错误的。

2.常量T&案例没有错误,也没有警告,但是错误的地址被传递给了函数。正如我们所知,引用的地址是变量的地址,引用指向。

Jonathan Wakely写道:

const引用导致创建临时的,您没有绑定到压缩字段


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