为什么 alignas 说明符会在 Clang 上抛出错误?
Why does the alignas specifier throw an error on Clang?
根据标准,new
表达式的语法允许提供 alignas
说明符和其他属性说明符。我已经看到其他代码使用它,但 GCC 会忽略属性说明符,即使它在最大对齐范围内,并且 Clang 会抛出错误。
alignas
说明符在 new
表达式中实际上有效吗?
- 如果它是有效的,为什么 Clang 拒绝我的代码,为什么 GCC 忽略我的属性,无论我请求什么对齐方式?
我不是要解决具体问题,我只是想了解标准。
int* example = new alignas(16) int[2];
// alignof(std::max_align_t) = 16
// sizeof(int) = 4, sizeof(example) = 8
海湾合作委员会:
prog.cc: In function 'int main()':
prog.cc:7:41: warning: attribute ignored [-Wattributes]
7 | int* example = new alignas(16) int[2];
| ^
prog.cc:7:41: note: an attribute that appertains to a type-specifier is ignored
叮当声:
prog.cc:7:24: error: an attribute list cannot appear here:
int* example = new alignas(16) int[2];
可在最新的 GCC 和 Clang 上重现,示例:http://cpp.sh/3hfl7
参考文献:
http://eel.is/c++draft/expr.new#nt:new-expression
new-type-id:
type-specifier-seq new-declarator opt
type-specifier-seq:
type-specifier attribute-specifier-seq opt
type-specifier type-specifier-seq
(new-type-id -> type-specifier-seq -> attribute-specifier-seq -> attribute-specifier -> alignment-specifier is permitted by grammar)
attribute-specifier-seq
可以包含对齐说明符。
好吧,您引用的语法指出 attribute-specifier-seq 出现在 type-specifier-seq 中必须在所有 类型说明符 之后发生。因此,根据 [dcl.type]/1:
,您必须将它放在这里,以便使属性属于前面的 int
new int attribute-specifier-seq [2];
根据 [expr.new]/6:
,您必须将它放在这里才能使属性属于数组类型
new int [2] attribute-specifier-seq;
您也可以组合它们:您可以为数组类型和元素类型设置不同的属性。但我认为语法不允许您将属性放在 int
.
之前
至于对齐说明符的具体问题:标准既不明确允许也不明确禁止将对齐说明符应用于 type-specifier 或 type- ID ([dcl.align]/1)。 Clang 似乎将该标准解释为禁止它。 GCC 似乎将该标准解释为允许它;然而,由于标准没有为对齐说明符指定任何语义,当它属于一个类型时,发出警告。考虑:
struct S {
int x alignas(16);
int alignas(16) y;
};
此处,S::x
的对齐要求为 16,但 S::y
的对齐说明符没有意义。所以如果你写 int alignas(16) y
,GCC 警告你是有意义的,这样你就会意识到你把它放在了错误的地方。
要强制分配的内存在 16 字节边界上对齐,请使用放置语法显式调用采用对齐参数的 operator new
的重载:
int* x = new (std::align_val_t(16)) int [2];
根据标准,new
表达式的语法允许提供 alignas
说明符和其他属性说明符。我已经看到其他代码使用它,但 GCC 会忽略属性说明符,即使它在最大对齐范围内,并且 Clang 会抛出错误。
alignas
说明符在new
表达式中实际上有效吗?- 如果它是有效的,为什么 Clang 拒绝我的代码,为什么 GCC 忽略我的属性,无论我请求什么对齐方式?
我不是要解决具体问题,我只是想了解标准。
int* example = new alignas(16) int[2];
// alignof(std::max_align_t) = 16
// sizeof(int) = 4, sizeof(example) = 8
海湾合作委员会:
prog.cc: In function 'int main()':
prog.cc:7:41: warning: attribute ignored [-Wattributes]
7 | int* example = new alignas(16) int[2];
| ^
prog.cc:7:41: note: an attribute that appertains to a type-specifier is ignored
叮当声:
prog.cc:7:24: error: an attribute list cannot appear here:
int* example = new alignas(16) int[2];
可在最新的 GCC 和 Clang 上重现,示例:http://cpp.sh/3hfl7
参考文献:
http://eel.is/c++draft/expr.new#nt:new-expression
new-type-id:
type-specifier-seq new-declarator opt
type-specifier-seq:
type-specifier attribute-specifier-seq opt
type-specifier type-specifier-seq
(new-type-id -> type-specifier-seq -> attribute-specifier-seq -> attribute-specifier -> alignment-specifier is permitted by grammar)
attribute-specifier-seq
可以包含对齐说明符。
好吧,您引用的语法指出 attribute-specifier-seq 出现在 type-specifier-seq 中必须在所有 类型说明符 之后发生。因此,根据 [dcl.type]/1:
,您必须将它放在这里,以便使属性属于前面的int
new int attribute-specifier-seq [2];
根据 [expr.new]/6:
,您必须将它放在这里才能使属性属于数组类型new int [2] attribute-specifier-seq;
您也可以组合它们:您可以为数组类型和元素类型设置不同的属性。但我认为语法不允许您将属性放在 int
.
至于对齐说明符的具体问题:标准既不明确允许也不明确禁止将对齐说明符应用于 type-specifier 或 type- ID ([dcl.align]/1)。 Clang 似乎将该标准解释为禁止它。 GCC 似乎将该标准解释为允许它;然而,由于标准没有为对齐说明符指定任何语义,当它属于一个类型时,发出警告。考虑:
struct S {
int x alignas(16);
int alignas(16) y;
};
此处,S::x
的对齐要求为 16,但 S::y
的对齐说明符没有意义。所以如果你写 int alignas(16) y
,GCC 警告你是有意义的,这样你就会意识到你把它放在了错误的地方。
要强制分配的内存在 16 字节边界上对齐,请使用放置语法显式调用采用对齐参数的 operator new
的重载:
int* x = new (std::align_val_t(16)) int [2];