将打包结构成员的引用传递给模板.gcc 错误?
我遇到了一个问题,将结构成员传递给模板函数.该函数的目标是获取成员的地址和大小.这是一个简单的例子:
I encountered a problem, passing struct member to a template function. The function's goal is to take the address and size of the member. Here is simple example:
这是结构.它具有打包属性.
This is the struct. It has packed attribute.
struct TestStruct {
unsigned char elem1;
unsigned char elem2;
uint64_t elem3;
char buf[10000];
int elem4;
unsigned char elem5;
}
__attribute__ ((packed));
这是模板函数,它应该得到一个成员的地址
this is the template function, which should get a member's address
template<typename T>
void addData(const T &val)
{
printf ("address inside func: %p
",&val);
}
int main(int argc, char *argv[])
{
TestStruct testdata;
testdata.elem4 = 0;
printf ("struct address is: %p
",&testdata);
printf ("elem4 address is: %p
",&testdata.elem4);
addData(testdata.elem4);
return 0;
}
问题:当属性((packed));已设置(如示例中所示)模板函数收到错误的成员地址:
The problem: When attribute ((packed)); is set (like in the example) the template function receives wrong address of the member:
输出:
struct address is: 0x7fff735bb4e0
elem4 address is: 0x7fff735bdbfa
address inside func: 0x7fff735bb4dc
如果我删除packed"属性,则一切正常.没有错误也没有警告(即使使用 -Wall -Wextra),但没有将正确的地址传递给函数.
If I remove the "packed" attribute, everything is OK. There is no error and no warning (even with -Wall -Wextra), but not the right address is passed to the function.
我读了这个:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
发现有一个问题,获取对packed-struct成员的引用.很有趣,替换 const T&与 T&在我的模板函数中,产生错误消息:
and found that there is an issue, getting references to packed-struct members. Interesting enough, replacing const T& with T& in my template function, produces the error message:
error: cannot bind packed field ‘testdata.TestStruct::elem4’ to ‘int&’
所以,我有两个问题:
当其地址可以作为指针传递时,为什么不能将压缩结构成员作为常量引用传递
Why cannot packed-struct members be passed as const references, when their address can be passed as pointer
const T& 中发生了什么案件?没有错误,没有警告,但错误的地址被传递给函数.众所周知,引用的地址就是引用指向的变量的地址.
What happens in the const T& case? There is no error, no warning, but the incorrect address is passed to the function. As we know, the address of reference is the address of the variable, the reference points to.
推荐答案
您的两个问题都在您发布的链接中得到解答.
Both of your questions are answered at the link you posted.
1.当它们的地址可以作为指针传递时,为什么不能将压缩结构成员作为常量引用传递
Gabriel M. Beddingfield 在他的评论中写道:
Gabriel M. Beddingfield wrote in his comment:
obj.s 对类型 short& 的所有赋值和 short* 不正确,理想情况下它们都会导致编译器错误.
All assignments of obj.s to type short& and short* are incorrect, and ideally they would all result in compiler errors.
C++ 规范(C++03,第 3.9、3.9.1、3.9.2 节)非常清楚 T 和指向 T 的指针"具有特定于实现的对齐要求.如果你有一个指向 T 的指针"那么您可以假设它满足对齐要求.我确定 C 规范有类似的语言.
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) 的相应引用:
I can only add to this the corresponding quote from C++14 standard ([basic.align]/1):
对象类型具有对齐要求(3.9.1、3.9.2),这对可以分配该类型对象的地址进行了限制.alignment 是一个实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数.对象类型对该类型的每个对象都强加了对齐要求;可以使用对齐说明符请求更严格的对齐
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
最重要的是,即使采用压缩结构成员的地址也应该是错误的.
The bottom line of it is that even taking an addres of a packed struct member should be an error.
2.const T& 中会发生什么?案件?没有错误,没有警告,但错误的地址被传递给函数.众所周知,引用的地址就是引用指向的变量的地址.
Jonathan Wakely 写道:
Jonathan Wakely wrote:
常量引用会导致创建一个临时对象,您没有绑定到打包字段
A const-reference causes a temporary to be created, you didn't bind to the packed field
最重要的是,您无法将非常量引用绑定到打包的结构字段,这本身不是错误,而是您可以同时获取它的地址.编译器应该允许或禁止两者.
The bottom line is that it's not a bug itself that you can't bind a non-const reference to a packed struct field, a bug is that at the same time you can take an address of it. The compiler should either allow or disallow both.
相关文章