为了使我的代码标准化并使其更具可移植性,我更换了
#ifdef __GNUC__
typedef __attribute__((aligned(16))) float aligned_block[4];
#else
typedef __declspec(align(16)) float aligned_block[4];
#endif
Run Code Online (Sandbox Code Playgroud)
同
typedef float alignas(16) aligned_block[4];
Run Code Online (Sandbox Code Playgroud)
在C++ 11中.然而,gnu(4.8)并不喜欢这样但是抱怨
test.cc:3:9: warning: attribute ignored [-Wattributes]
typedef float alignas(16) aligned_block[4];
^
test.cc:3:9: note: an attribute that appertains to a type-specifier is ignored
Run Code Online (Sandbox Code Playgroud)
而clang 3.2没有发出警告(即使有-Weverything -Wno-c++98-compat -pedantic
).所以我想知道我上面的代码是否正确,更一般地说,我alignas()
可以在哪里放置.
编辑(2013年4月):
该标准的相关文章是7.6.2,特别是7.6.2.1
对齐说明符可以应用于变量或类数据成员,但不应该应用于位字段,函数参数,catch子句的形式参数(15.3)或使用注册存储类说明符.对齐说明符也可以应用于类或枚举类型的声明.带省略号的对齐说明符是包扩展(14.5.3).
正如Red XIII已经挖出来的那样.但是,我不够专业,不知道这对我上面的测试意味着什么.
如果clang接受我的属性这一事实意味着什么,那么也许值得一提的是,当试图使用using
指令代替a时typedef
,clang也会抱怨.此外,与此问题的早期版本中的陈述相反,gcc不仅警告,而且实际上忽略了我对齐的愿望.
我试图理解如何使用alignas,我想知道它是否可以替代pragma pack,我已经努力验证它但没有运气.使用gcc 4.8.1(http://ideone.com/04mxpI)我总是在STestAlignas下面获得8个字节,而使用pragma pack时它是5个字节.我想要的是使sizeof(STestAlignas)返回5.我尝试在clang 3.3上运行此代码(http://gcc.godbolt.org/)但我收到错误:
!!错误:对于'long'类型,请求的对齐小于8的最小对齐 - 正好在alignas使用之下.
那么也许对齐有最小的对齐值?
下面是我的测试代码:
#include <iostream>
#include <cstddef>
using namespace std;
#pragma pack(1)
struct STestPragmaPack {
char c;
long d;
} datasPP;
#pragma pack()
struct STestAttributPacked {
char c;
long d;
} __attribute__((packed)) datasAP;
struct STestAlignas {
char c;
alignas(char) long d;
} datasA;
int main() {
cout << "pragma pack = " << sizeof(datasPP) << endl;
cout << "attribute packed = " << sizeof(datasAP) << endl;
cout << "alignas …
Run Code Online (Sandbox Code Playgroud) 我在查找有关GCC的对齐新警告和gcc -faligned-new选项的更多信息时遇到了一些困难.在gcc 7.2.0上编译(没有--std = c ++ 17)并尝试定义一个对齐的结构,例如:
struct alignas(64) Foo { int x; }
Run Code Online (Sandbox Code Playgroud)
做一个简单的旧:
Foo * f = new Foo();
Run Code Online (Sandbox Code Playgroud)
给我以下警告和建议:
alignas.cpp:36:25: warning: ‘new’ of type ‘Foo’ with extended alignment 64 [-Waligned-new=]
Foo * f = new Foo();
^
alignas.cpp:36:25: note: uses ‘void* operator new(long unsigned int)’, which does not have an alignment parameter
alignas.cpp:36:25: note: use ‘-faligned-new’ to enable C++17 over-aligned new support
Run Code Online (Sandbox Code Playgroud)
据我所知,默认情况下new
只返回内存对齐alignof( std::max_align_t )
(对我而言是16),但我不清楚的是,如果我传递-faligned-new,gcc现在会new
代表我强制执行新的对齐吗?
不幸的是,关于这个的gcc文档非常缺乏.
在C中,可以使用malloc(sizeof(T)*N)分配动态数组,然后使用指针算法在此动态数组中获取i偏移的元素.
在C++中,可以使用operator new()以与malloc()相同的方式执行类似的操作,然后使用new(例如,可以在书中看到第13项的解决方案"Exceptional C++:47工程难题,编程问题和解决方案"通过Herb Sutter).如果您没有,则此问题的解决方案摘要如下:
T* storage = operator new(sizeof(T)*size);
// insert element
T* p = storage + i;
new (p) T(element);
// get element
T* element = storage[i];
Run Code Online (Sandbox Code Playgroud)
对我来说,这看起来是合法的,因为我要求一大块内存,有足够的内存来容纳n个对齐的size = sizeof(T)元素.因为sizeof(T)应该返回一个对齐的元素的大小,并且它们在一块内存中一个接一个地放置,所以在这里使用指针算法是可以的.
然而,我随后指出了以下链接:http://eel.is/c++draft/expr.add#4或http://eel.is/c++draft/intro.object#def:object并声称在C++运算符new()中没有返回一个数组对象,因此对它返回的内容进行指针算术并将其用作数组是未定义的行为,而不是ANSI C.
我不是很擅长这么低级别的东西而且我真的想通过阅读这个来理解:https ://www.ibm.com/developerworks/library/pa-dalign/或者这个:http:// jrruethe. github.io/blog/2015/08/23/placement-new/但我还是不明白,如果萨特是完全错误的?
我确实理解alignas在构造中是有意义的,例如:
alignas(double) char array[sizeof(double)];
Run Code Online (Sandbox Code Playgroud)
(c)http://georgeflanagin.com/alignas.php
如果数组看起来不在double的边界内(可能是在2字节读取处理器的结构中跟随char).
但这是不同的 - 我已经从堆/空闲存储请求内存,特别是请求的操作符new返回内存,该内存将保持与sizeof(T)对齐的元素.
总结一下这是TL; DR:
对不起,如果这是愚蠢的.
我正在尝试使用alignas
作为类成员的指针,坦率地说,我不确定我应该把它放在哪里.
例如:
class A
{
private:
int n;
alignas(64) double* ptr;
public:
A(const int num) : n(num), ptr(new double[num])
{}
};
Run Code Online (Sandbox Code Playgroud)
我希望能确保ptr的数据在64字节块上对齐.使用英特尔编译器,它没有.
有人能指出我正确的方向吗?
在为32位x86 linux运行以下代码时,我得到了意想不到的结果(编译器标志:g ++ -std = c ++ 14 -m32).我试过gcc和clang.
#include <iostream>
using namespace std;
struct S1
{
uint64_t a;
uint32_t b;
};
struct S2
{
alignas(uint64_t) char a[8];
uint32_t b;
};
int main()
{
cout << "sizeof(S1)=" << sizeof(S1) << endl;
cout << "sizeof(S2)=" << sizeof(S2) << endl;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
sizeof(S1)=12
sizeof(S2)=16
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?为什么S1和S2的尺寸不同?据我了解,64位整数值在32位x86机器上与32位对齐.这解释了为什么S1的大小是12个字节.但为什么这不适用于S2呢?
我想在缓存边界上输入我的类型,所以我使用了alignas
:
struct alignas(64) W { };
Run Code Online (Sandbox Code Playgroud)
编译好了.但是,令我惊讶的是,当我尝试分配一堆W
s时,它们不是64字节对齐但实际上是16字节对齐的:
#include <iostream>
#include <iomanip>
#include <unordered_map>
struct alignas(64) W { };
int main() {
std::unordered_map<int, int> offset;
for (int i = 0; i < 1000; ++i) {
auto w = new W;
offset[(uintptr_t)w % 64]++;
}
for (const auto& p : offset) {
std::cout << p.first << ' ' << p.second << '\n';
}
}
Run Code Online (Sandbox Code Playgroud)
产量:
0 250
16 250
32 250
48 250
Run Code Online (Sandbox Code Playgroud)
几个编译(gcc 4.8.2,gcc 5.2.0,clang 3.7.1).这是怎么回事?我告诉它要对齐,为什么不对齐?
我在 clang 上遇到编译错误,并使用以下代码对 gcc 发出警告:
static alignas(16) int one_s = 1; // clang: error: an attribute list cannot appear here; gcc: warning: attribute ignored;
static __attribute__((aligned(16))) int zero_s = 0; // on the other hand this works well on both compilers...
alignas(16) int one = 1; // this also works on both compilers
__attribute__((aligned(16))) int zero = 0; // as well as this
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么在包含 static 关键字的声明中不接受alignas?我将 --std=c++11 编译器选项与 gcc 和 clang 一起使用。(编辑:我使用 clang 3.4 及更高版本和 gcc 4.8 及更高版本)
请注意,使用 Visual …
C++23 中已弃用的使用aligned_storage
,建议用对齐方式替换std::byte[]
(请参阅此处)。我对此有两个问题:
1.如何对齐?
该文件建议更换
std::aligned_storage_t<sizeof(T), alignof(T)> t_buff;
和
alignas(T) std::byte t_buff[sizeof(T)]
。
然而,我实际上存储的是一个 T 数组(或者 T 是一个数组)。我可以简单地替换
std::aligned_storage_t<sizeof(T), alignof(T)> data_[SIZE];
为
alignas(alignof(T)*SIZE) std::byte data_[sizeof(T) * SIZE];
?
我认为这是错误的用法alignas
吗?
2. 如何读/写?
我认为访问权限没有太大变化,因此阅读是否正确:
reference data(size_t index) noexcept {
return *std::launder(reinterpret_cast<T*>(&data_[index*sizeof(T)]));
}
Run Code Online (Sandbox Code Playgroud)
并写与
new (reinterpret_cast<void*>(&data_[size_*sizeof(T)])) T{std::forward<Args>(args)...};
?
我为什么要问?
我的使用alignas
似乎确实错误,我应该如何对齐它?我真的可以将访问索引与 相乘sizeof(T)
,还是需要考虑填充?如何?
另外,代码似乎比以前更糟糕,因为我必须sizeof()
到处插入。
当我运行它时它似乎有效,但我不确定这是否真的保存。
这个程序:
struct alignas(4) foo {};
int main() { return sizeof(foo); }
Run Code Online (Sandbox Code Playgroud)
返回 4,包含 GCC 10.1 和 clang 10.1,以及 icc 19.0.1。
这让我想知道 - 是否必须alignas()
以sizeof()
这种方式影响?即增加超出结构最初大小的大小?或者 - 这种变化只是实现的特权吗?
在32位计算机中,一个内存读取周期获取4 bytes
个数据。
因此要读取下面的缓冲区,读取下面提到的128个缓冲区应该花费32个读周期bytes
。
char buffer[128];
Run Code Online (Sandbox Code Playgroud)
现在,假设如果我按如下所述对齐了该缓冲区,那么请让我知道它将如何使其更快地读取?
alignas(128) char buffer[128];
Run Code Online (Sandbox Code Playgroud)
我假设内存读取周期将仅保留4个字节。