我有项目我从32位窗口移植到64位,其中包括可简化如下的代码;
void FuncA(double &x)
{
x = 0;
}
void FuncB(double *x)
{
*x = 0;
}
#pack(1)
struct
{
char c;
double x;
} MyStruct;
#pack();
void MyFunc()
{
MyStruct M;
FuncA(M.x); // This is OK
FuncB(&M.x); // This generates a warning C4366
}
在针对64位的VS2010 SP1下进行编译时,使用压缩结构的成员调用FuncB
会生成以下警告;
警告C4366:一元'&'的结果运营商可能未对齐
而调用FuncA
却没有。我原以为这两种情况都会编译成几乎相同的代码。引用在某些方面比对等指针更安全吗?或者MSVC根本不发出警告应该在哪里?该项目需要维护结构包装,因此我的选择是将FuncB
更改为
void FuncB(__unaligned double *x)
{
*x = 0;
}
或在所有这些情况下简单地使用FuncA
。后者会更好,因为它更便携,但我想知道它是否会起作用,或者在参考案例中缺少警告只是编译器中的一个缺点。
修改:此错误的Microsoft帮助条目为here。 __unaligned帮助表明,如果不注意此警告,将导致在Itanium处理器上抛出异常。进一步在MSDN周围进行拖网示意there may be issues surrounding unaligned references。虽然这可能不会给我当前的用户带来问题,但如果Itanium架构在未来得到更广泛的使用,我可能会设置一个支持噩梦。 Plan现在是为使用压缩结构的所有函数添加特定包装器,以避免使用指针和__unaligned关键字。
答案 0 :(得分:8)
参考和指针几乎是一回事(在引擎盖下,可以这么说),所以从安全角度来看,它并没有什么不同。它可能更多的是疏忽和/或编译器不太关注引用,因为它们不能在C ++环境之外传递(尽管我倾向于认为它是' ;只是一个疏忽)。
也可能是编译器更关注指针,因为指针更有可能用于性能,您希望迭代一系列double
值(例如,通过分配更多的空间) struct本身使用,并在其后存储更多的double
值 - 你不能用引用来做到这一点。由于未对齐访问至少比对齐访问慢,这可能会对性能产生影响,并且在某些系统中,它会导致操作系统陷阱,它将“修复”"未对齐的访问(以比普通对齐访问速度慢的几个命令的速度),或操作系统只是说"你的程序导致了一个未对齐的访问,我杀了它"。
多线程也存在问题,因为未对齐访问可能无法以原子方式更新数据。当然,您应该使用std::atomic
或类似的线程来共享数据。
x86完全能够从未对齐的地址读取double
。我认为Itanium不是,但从统计学角度来说,我怀疑你还没有使用过该处理器。其他较旧的架构,如Alpha可能在读取未对齐的内存时遇到问题。