Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where can I use alignas() in C++11?

In an effort to standardize my code and make it more portable, I replaced

#ifdef __GNUC__ typedef __attribute__((aligned(16))) float aligned_block[4]; #else typedef __declspec(align(16)) float aligned_block[4]; #endif 

with

typedef float alignas(16) aligned_block[4]; 

in C++11. However, gnu (4.8) doesn't like that but complains

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 

whereas clang 3.2 creates no warning (even with -Weverything -Wno-c++98-compat -pedantic). So I wonder whether my code above is correct and, more generally, where alignas() can and cannot be placed.

EDIT (Apr 2013):

The relevant article from the standard is 7.6.2, in particular 7.6.2.1

An alignment-specifier may be applied to a variable or to a class data member, but it shall not be applied to a bit-field, a function parameter, the formal parameter of a catch clause (15.3), or a variable declared with the register storage class specifier. An alignment-specifier may also be applied to the declaration of a class or enumeration type. An alignment-specifier with an ellipsis is a pack expansion (14.5.3).

as already dug out by Red XIII. However, I'm not expert enough to know what this means for my test above.

If the fact that clang accepts my attribute means anything, it's perhaps worth mentioning that when trying to use a using directive instead of a typedef, clang also complains. Also, contrary to a statement in an earlier version of this question, gcc does not only warn, but indeed ignores my wish for alignment.

like image 770
Walter Avatar asked Apr 03 '13 13:04

Walter


People also ask

Why use alignas?

Use 1 - Avoiding unnecessary invalidation of data from cache line You can use alignas to keep the addresses or objects used by separate threads running on separate cache lines, so that one thread does not inadvertently invalidate cache line of another core.

What is alignment requirement in C?

Every complete object type has a property called alignment requirement, which is an integer value of type size_t representing the number of bytes between successive addresses at which objects of this type can be allocated.

How does Alignof work C++?

alignof operator in C++ In C++11 the alignof operator used to returns the alignment, in bytes of the specified type. Syntax Explanation: alignof: operator returns the alignment in byte, required for instances of type, which type is either complete type, array type or a reference type.

What is memory alignment C?

When the database server passes the data type to a UDR, it aligns opaque-type data on a specified byte boundary. Alignment requirements depend on the C definition of the opaque data type and on the system (hardware and compiler) on which the opaque data type is compiled.


1 Answers

I think you just placed the alignas in the wrong position. If you move it directly after the identifier, both GCC and Clang are happy and apply the alignment:

typedef float aligned_block alignas(16) [4]; typedef float aligned_block [4] alignas(16); 

this is also true if you use using, where the difference also becomes more apparent. Here are two versions that are not accepted by GCC (warning, alignment ignored):

using aligned_block = float alignas(16)[4]; using aligned_block = float[4] alignas(16); 

and here's the accepted one:

using aligned_block alignas(16) = float[4]; 

I think that GCC applies

7.1.3 The typedef specifier [dcl.typedef]

2 A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics as if it were introduced by the typedef specifier. [...]

(emphasis mine)

The above is quite clear for using, the rules for typedef are spread through several paragraphs, including at the end of §8.3/1, where you find:

8.3 Meaning of declarators [dcl.meaning]

1 [...] The optional attribute-specifier-seq following a declarator-id appertains to the entity that is declared.

(again, emphasis mine)


Update: The above answer concentrated on where the alignas has to be placed, not on its exact meaning. After thinking about it some more, I still think that the above should be valid. Consider:

7.6.2 Alignment Specifier [dcl.align]

1An alignment-specifier may be applied to a variable or to a class data member, but it shall not be applied to a bit-field, a function parameter, an exception-declaration (15.3), or a variable declared with the register storage class specifier. An alignment-specifier may also be applied to the declaration or definition of a class (in an elaborated-type-specifier (7.1.6.3) or class-head (Clause 9), respectively) and to the declaration or definition of an enumeration (in an opaque-enum-declaration or enum-head, respectively (7.2)). An alignment-specifier with an ellipsis is a pack expansion (14.5.3).

It lists cases where it can be clearly applied and it lists cases where it clearly can not be applied. The above question's example is neither.

One could also argue that the type alias created by typedef or using is carrying the alignment specification as part of the aliased type. This alias can than be used to create a variable, etc. as allowed by 7.6.2p1 but not to create a variable with register, etc.

In that sense I think that the attribute specifier is applied (in the sense of 7.6.2) in a deferred way and thus OPs example should still be valid when the alignment specification is put in the syntactically correct place.

like image 92
Daniel Frey Avatar answered Sep 23 '22 15:09

Daniel Frey