为什么此代码与MSVC无效对齐?

时间:2014-06-04 19:23:32

标签: c++ visual-c++ c++11 memory-alignment

我已在ideone.com上测试了此代码,并按原样输出16。但是,当我在Visual Studio 2013中尝试它时,它显示8。它是编译器的错误还是缺乏对C ++ 11的支持?

#include <iostream>
#include <type_traits>
using namespace std;
using float_pack = aligned_storage<4 * sizeof(float), 16>::type;
int main() {

    cout << alignment_of<float_pack>::value << endl;
    return 0;
}

我使用了alignment_of,因为MSVC不支持alignof

修改:我发现我无法16aligned_storage对齐。但为什么这个片段没问题?

#include <iostream>
#include <type_traits>
#include <xmmintrin.h>
using namespace std;

__declspec(align(16)) struct float_pack {
    float x[4];
};

int main()
{
    cout << alignment_of<float_pack>::value << endl;
}

输出为16。这是否意味着编译器在使用扩展时可以提供更大的对齐?为什么我无法使用aligned_storage获得相同的结果?只是因为MSVC没有提供aligned_storage

2 个答案:

答案 0 :(得分:6)

看起来std::max_align_t8see it live

std::cout << alignment_of<std::max_align_t>::value << '\n';

draft C++ standard部分3.11 对齐中,它说:

  

基本对齐由小于或等于所有上下文中实现所支持的最大对齐的对齐来表示,其等于alignof(std :: max_align_t)(18.2)。[...] < / p>

哪个说这是实现支持的最大对齐,这似乎是由boost doc支持的,其中说:

  

扩展对齐由大于alignof(std :: max_align_t)的对齐表示。它是实现定义的,是否支持任何扩展对齐以及支持它们的上下文。具有扩展对齐要求的类型是过度对齐类型。

max_align_t符合詹姆斯告知我们8 bytes的基本对齐标准。虽然扩展名不必坚持,只要记录在案,如果我们阅读__declspec align的文档,我们会看到它说:

  

编写使用最新处理器指令的应用程序   介绍了一些新的约束和问题。特别是很多新的   指令要求数据必须与16字节边界对齐。   此外,通过将常用数据与高速缓存行大小对齐   对于特定处理器,您可以提高缓存性能。例如,   如果你定义一个大小小于32字节的结构,你可以   想要将其对齐到32个字节以确保该结构的对象   类型被高效缓存。

     

[...]

     

没有__declspec(align(#)),Visual C ++会自然地对齐数据   基于数据大小的边界,例如4字节整数   在4字节边界和8字节边界上的8字节双精度。数据输入   类或结构在类或结构内对齐   最小的自然对齐和当前打包设置(来自#pragma pack或/ Zp编译器选项)。

答案 1 :(得分:2)

std::aligned_storage定义了一种大小为Len的类型,其中包含您提供的对齐要求。如果您要求不支持对齐,则您的程序格式不正确。

template <std::size_t Len, std::size_t Align
    = default-alignment > struct aligned_storage;
  

Len不得为零。对于某些类型alignof(T)默认对齐,对齐应等于T

     

对于任何大小不大于Len(3.9)的C ++对象类型, default-alignment 的值应该是最严格的对齐要求。成员typedef类型应为POD类型,适合用作任何大小为Len且对齐为Align除数的对象的未初始化存储。

     

[注意:典型的实现会将aligned_storage定义为:

template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
    typedef struct {
        alignas(Alignment) unsigned char __data[Len];
    } type;
};
  

-end note]

对于alignas

  

7.6.2对齐说明符[dcl.align]

     

1对齐说明符可以应用于变量或类数据成员,但不应该应用于位字段,函数参数,catch子句的形式参数(15.3)或者用寄存器存储类说明符声明的变量。对齐说明符也可以应用于类或枚举类型的声明。带省略号的对齐说明符是包扩展(14.5.3)   2当alignment-specifier的格式为alignas(assignment-expression)时:
   - 赋值表达式应为整数常量表达式
   - 如果常量表达式求值为基本对齐,则对齐要求   声明的实体应为指定的基本对齐
   - 如果常量表达式求值为扩展对齐,并且实现支持该扩展   在声明的范围内对齐,声明的实体的对齐应为对齐    - 如果常量表达式求值为扩展对齐并且实现不支持
  在宣言的背景下,该方案形成不良    - 如果常量表达式求值为零,则对齐说明符应无效    - 否则,该程序是不正确的。