我遇到了一个问题,将struct成员传递给模板函数。该功能的目标是获取成员的地址和大小。这是一个简单的例子:
这是结构。它有打包属性。
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;
}
问题:属性((打包));已设置(如示例中所示) 模板函数接收成员的错误地址:
输出:
struct address is: 0x7fff735bb4e0
elem4 address is: 0x7fff735bdbfa
address inside func: 0x7fff735bb4dc
如果我删除&#34;打包&#34;属性,一切都好。 没有错误也没有警告(即使使用-Wall -Wextra),但没有将正确的地址传递给函数。
我读到了这个:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
并发现存在问题,获取对packed-struct成员的引用。 有趣的是,取代const T&amp;与T&amp;在我的模板函数中,生成错误消息:
error: cannot bind packed field ‘testdata.TestStruct::elem4’ to ‘int&’
所以,我有两个问题:
为什么packed-struct成员不能作为const引用传递,当它们的地址可以作为指针传递时
const T&amp;案件?没有错误,没有警告,但是错误的地址被传递给函数。我们知道,引用的地址是变量的地址,引用指向。
答案 0 :(得分:3)
您的所有问题都会在您发布的链接中得到解答。
1。为什么pack-struct成员不能作为const引用传递,因为它们的地址可以作为指针传递
Gabriel M. Beddingfield在his comment写道:
obj.s的所有分配键入短&amp;和short *是不正确的,理想情况下它们都会导致编译器错误。
C ++规范(C ++ 03,Sects.3.9,3.9.1,3.9.2)非常清楚T和“T指针”具有特定于实现的对齐要求。如果你有一个“T指针”,那么你可以认为它符合对齐要求。我确定C规范有类似的语言。
我只能在C ++ 14标准([basic.align] / 1)中添加相应的引用:
对象类型具有对齐要求(3.9.1,3.9.2),它对可以分配该类型的对象的地址施加限制。 alignment 是一个实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。对象类型对该类型的每个对象强制对齐要求;可以使用对齐说明符
请求更严格的对齐
它的底线是即使采用压缩结构成员的地址也应该是一个错误。
2。 const T&amp; amp;案件?没有错误,没有警告,但是错误的地址被传递给函数。我们知道,引用的地址是变量的地址,引用指向。
Jonathan Wakely wrote:
const-reference导致创建临时,但未绑定到压缩字段
最重要的是,你不能将非const引用绑定到打包的struct字段本身并不是一个错误,一个错误就是你可以同时获取它的地址。编译器应该允许或禁止两者。