In the latest draft of the c++11 standard, chapter 3.11 talks about the alignment.
Later, the chapter 7.6.1 defines how to define an aligned structures (or variables?)
If I define a structure like this :
alignas(16) struct A
{
int n;
unsigned char[ 1020 ];
};
does it means that all instances of the class A are going to be aligned to 16 bytes?
Or, do I have to do it like in the next code?
struct A
{
char data[300];
};
alignas(16) A a;
If both examples are wrong, how to do it properly?
PS I am not looking for a compiler dependent solution.
Alignment is first and foremost a property of types.
It can be overridden for a type with alignas; alignas can also be used to assign a new alignment value to a specific object.
So, both examples are valid, and will have the semantics that you've presumed.
[n3290: 3.11/1]: Object types have alignment requirements (3.9.1,
3.9.2) which place restrictions on the addresses at which an object of
that type may be allocated. An alignment is an implementation-defined
integer value representing the number of bytes between successive
addresses at which a given object can be allocated. An object type
imposes an alignment requirement on every object of that type;
stricter alignment can be requested using the alignment specifier
(7.6.2).
[n3290: 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).
[n3290: 7.6.2/2]: When the alignment-specifier is of the form
alignas( assignment-expression ):
the assignment-expression shall be an integral constant expression
if the constant expression evaluates
to a fundamental alignment, the alignment requirement of the declared
entity shall be the specified fundamental alignment
if the constant
expression evaluates to an extended alignment and the implementation
supports that alignment in the context of the declaration, the
alignment of the declared entity shall be that alignment
if the
constant expression evaluates to an extended alignment and the
implementation does not support that alignment in the context of the
declaration, the program is ill-formed
if the constant expression
evaluates to zero, the alignment specifier shall have no effect
otherwise, the program is ill-formed.
Related
I believe that until C++14 a bit field of a struct declared as int was still interpreted as either signed or unsigned, the interpretation being implementation defined. Reference: http://en.cppreference.com/w/cpp/language/bit_field.
Is this still the case in C++14? I.e., is the code below guaranteed to work as inteded?
#include <iostream>
struct X
{
int f:3;
};
int main()
{
X x;
x.f = -2; // is this going to be indeed signed? It seems so.
std::cout << x.f << std::endl; // displays -2
}
According to C++11 standard §9.6/p3 Bit-fields [class.bit] (Emphasis Mine):
A bit-field shall not be a static member. A bit-field shall have
integral or enumeration type (3.9.1). It is implementation-defined
whether a plain (neither explicitly signed nor unsigned) char, short,
int, long, or long long bit-field is signed or unsigned. A bool value
can successfully be stored in a bit-field of any nonzero size. The
address-of operator & shall not be applied to a bit-field, so there
are no pointers to bitfields. A non-const reference shall not be bound
to a bit-field (8.5.3). [ Note: If the initializer for a reference of
type const T& is an lvalue that refers to a bit-field, the reference
is bound to a temporary initialized to hold the value of the
bit-field; the reference is not bound to the bit-field directly. See
8.5.3. —end note ]
So you're correct for the first part. Indeed until C++14 a bit field of a struct declared as signed was still interpreted as either signed or unsigned, the interpretation being implementation defined.
As already mentioned in this comments by #T.C. Defect reports referring to the issue were made DR739, DR675. Resulting in the following resolutions in C++14 standard:
The wording "It is implementation-defined whether a plain (neither explicitly signed nor unsigned) char, short, int, long, or long long bit-field is signed or unsigned.", was removed, and the C++14 wording now is:
A bit-field shall not be a static member. A bit-field shall have
integral or enumeration type (3.9.1). A bool value can successfully be
stored in a bit-field of any nonzero size. The address-of operator &
shall not be applied to a bit-field, so there are no pointers to
bit-fields. A non-const reference shall not be bound to a bit-field
(8.5.3). [ Note: If the initializer for a reference of type const T&
is an lvalue that refers to a bit-field, the reference is bound to a
temporary initialized to hold the value of the bit-field; the
reference is not bound to the bit-field directly. See 8.5.3. —end note
]
Also in §C.1.8 Clause 9: classes [diff.class] the following section was added:
9.6
Change: Bit-fields of type plain int are signed.
Rationale: Leaving the choice of signedness to implementations could lead to inconsistent definitions of
template specializations. For consistency, the implementation freedom was eliminated for non-dependent
types, too.
Effect on original feature: The choice is implementation-defined in C, but not so in C++.
Difficulty of converting: Syntactic transformation.
How widely used: Seldom.
Consequently, in C++14 bit-fields of type plain int are signed and the code posted is guaranteed to work as intended.
Is it safe to reinterpret a pointer to an unqualified type as a pointer to a qualified type? Consider a standard layout type containing a pointer member "void *ptr" and another standard layout type defined equivalently, but with "const void *ptr". Are these types layout compatible, and does this answer depend on the language revision or between C and C++?
Motivation:
Sometimes when interfacing with C programs, one defines a struct grouping parameters to some type of buffer. For const-correctness, an input buffer should have const pointers to underlying buffers, but output buffers must obviously be mutable.
struct s1 { const void *ptr; }
struct s2 { void *ptr; }
const void *get_in_ptr(void);
void *get_out_ptr(void);
void alg(const s1 *in, const s2 *out);
void f()
{
s1 in_arg = { get_in_ptr() };
s2 out_arg1 = { get_out_ptr() };
s2 out_arg2 = { get_out_ptr() };
/* First algorithm pass. */
alg(&in_arg, &out_arg1);
/* Second algorithm pass. */
alg((const s1 *)&out_arg1, &out_arg2); /* Is this legal? */
}
Please cite the relevant standard publications in any answers.
C11 states:
For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.
So, it is safe to cast to a qualified version, but not vice-versa. Casting away - especially const or volatile could use different memory accesses, e.g. for Harvard architectures storing const variables in program memory (PIC, AVR). And the standard is very clear about the consequences:
If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
Briefly: it is not safe to cast away those qualifiers in general. The standard does not mention read-accesses for ex-const objects, however.
For the other qualifiers and further details, please read yourself.
For the struct layout: C uses compatibility by type/layout, as opposed to C++. So two types are compatible if they use the same layout/standard type, not the same type-name.
[C99: 6.2.5/25, C11: 6.2.5/26]: [..] The qualified or unqualified versions of a type are distinct types that belong to the same type category and have the same representation and alignment requirements. [..]
[C++03, C++11, C++14: 3.9.3/1]: [..] The cv-qualified or cv-unqualified versions of a type are distinct types; however, they shall have the same representation and alignment requirements (3.11).
And for the encapsulating types:
[C99: 6.2.7/1]: [..] Moreover, two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are complete types, then the following additional requirements apply: there shall be a one-to-one correspondence between their members such that each pair of corresponding members are declared with compatible types, and such that if one member of a corresponding pair is declared with a name, the other member is declared with the same name. [..]
[C++03: 9.2/14]: Two POD-struct (clause 9) types are layout-compatible if they have the same number of nonstatic data members, and corresponding nonstatic data members (in order) have layout-compatible types (3.9).
[C++11: 9.2/16, C++14: 9.2/17]: Two standard-layout struct (Clause 9) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types (3.9).
So, assuming we're ignoring the type system bypass (const void* → void* through const_cast either directly or by C-style cast — note that reinterpret_cast has nothing to do with this and is explicitly prohibited from dropping cv-qualifiers) and only talking about aliasing compatibility…
…yes, this is "safe".
It's why we're able to use const_cast, delicately, when ancient C APIs force us to take them at their word rather than actually using const-safety.
You know this is okay anyway, because when you wrote &in_arg your compiler implicitly converted the s1* to const s1* for the call, and did not complain.
I was just wondering... Let's say I have a POD structure in C++. If I would put a static_assert in there, will it ruin the fact that it's a POD?
I know I can easily put it somewhere else, I'm just asking because I'm interested if I should or shouldn't do this...
In other words (more specific):
#include <iostream>
#include <type_traits>
struct A
{
void* ptr;
static_assert(sizeof(void*) == 8, "Pointer should have size 8; platform unsupported");
};
int main()
{
// Is it guaranteed that this will evaluate to 'true'?
std::cout << std::is_pod<A>::value << std::endl;
}
In C++11 a type is deemed POD if it's
trivial (a scalar type, a trivially copyable class with a trivial default constructor, or array of such type/class)
standard layout (has no virtual functions, no virtual base classes, etc.)
Basically nothing that would hinder copying objects as if they're just constituted by raw bytes.
static_asserts are there to validate something at compile-time and doesn't change the object layout or the triviality (or the lack thereof) in constructing, copying, etc. of an object. Hence adding any number of static asserts to a type (struct/class) shouldn't change the POD-ness of it.
You can check if the compiler is considering a type as POD using std::is_pod<T>::value. This wouldn't change before and after adding static_asserts to it.
This is all that the standard says regarding static_asserts. From [dcl.dcl]:
In a static_assert-declaration the constant-expression shall be a constant expression that can be contextually converted to bool. If the value of the expression when so converted is true, the declaration has no effect. Otherwise, the program is ill-formed, and the resulting diagnostic message (1.4) shall include the text of the string-literal, except that characters not in the basic source character set (2.3) are not required to appear in the diagnostic message.
The following snippet works fine in Clang 3.5 but not in GCC 4.9.2:
int main()
{
constexpr volatile int i = 5;
}
with error:
error: both 'volatile' and 'constexpr' cannot be used here
If I inspect the assembly that Clang generates, it shows 5 as expected:
movl $5, -4(%rsp)
In GCC, constexpr int i = 5 is optimized away, but volatile int i = 5 also shows 5 in the assembly. volatile const int i = 5 compiles in both compilers. It's not a foreign concept for something to be both volatile and const at the same time.
Which compiler is correct by the standards?
Yes, this is valid, there was defect report 1688: Volatile constexpr variables that was filed for this, saying:
There does not appear to be language in the current wording stating
that constexpr cannot be applied to a variable of volatile-qualified
type. Also, the wording in 5.19 [expr.const] paragraph 2 referring to
“a non-volatile object defined with constexpr” might lead one to infer
that the combination is permitted but that such a variable cannot
appear in a constant expression. What is the intent?
it was rejected as not a defect(NAD), the response and rationale was:
The combination is intentionally permitted and could be used in some
circumstances to force constant initialization.
As the DR points out such a variable is itself not usable in a constant expression:
constexpr volatile int i = 5;
constexpr int y = i ; // Not valid since i is volatile
Section [expr.const]/2 includes all the cases that makes a conditional-expression not a core constant expression including:
an lvalue-to-rvalue conversion (4.1) unless it is applied to
and all the exception require:
[...]that refers to a non-volatile [...] object [...]
Quoting N4140 [dcl.constexpr]/9:
A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized.
Literal type is defined in [basic.types]/10:
A type is a literal type if it is:
(10.1) — void; or
(10.2) — a scalar type; or
(10.3) — a reference type; or
(10.4) — an array of literal type; or
(10.5) — a class type (Clause 9) that has all of the following properties:
(10.5.1) — it has a trivial destructor,
(10.5.2) — it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
(10.5.3) — all of its non-static data members and base classes are of non-volatile literal types.
Scalar type is in paragraph 9:
Arithmetic types (3.9.1), enumeration types, pointer types, pointer to member types (3.9.2), std::nullptr_t, and cv-qualified versions of these types (3.9.3) are collectively called scalar types.
int is arithmetic, so volatile int is a scalar type and hence a literal type. constexpr volatile int i = 5; is thus a well-formed declaration.
Interestingly, an expression that evaluates i cannot be a core-constant-expression since it applies an lvalue-to-rvalue conversion to a glvalue of volatile type ([expr.const]/2). Consequently, expressions that evaluate i are neither integral constant expressions nor constant expressions. I'm not sure that the constexpr in that declaration has any effect beyond making i implicitly const, and (nod to #T.C.) requiring its initializer to be a constant expression.
I've reported this as GCC bug 65327, we'll see what the GCC folks have to say.
2015-03-16 Update: Bug has been fixed for GCC 5.
As we all know, the array length in C++ must be determined. Then we can use:
const int MAX_Length=100;
or:
#define MAX_LENGTH 100
to determined the length of an array before compilation. But, when I read the book c++ primer by lippman, in chapter 3.5.1 in 5th Edition, it says: the length of an array must be an constant expression. Then the problem comes:
typedef enum Length{LEN1=100, LEN2, LEN3, LEN4}LEN;
LEN MAX_Length=LEN2; //101
int iArray[LEN2]; //attention
the code compiled successfully in mingw32-g++. But failed in VS2008, and the errors are:
error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2133: 'iArray' : unknown size
And I think the enum value is constant, so it should be used as an array's length. right?
I am confused, could you help me? Thank you.
In both C++11 and C++03 enumerators(unscoped enums in C++11) are integer constant expressions and therefore usable an array bounds. We can see this for C++11 by going to the draft C++11 standard section 5.19 [expr.const] which says:
An integral constant expression is an expression of integral or
unscoped enumeration type, implicitly converted to a prvalue, where
the converted expression is a core constant expression. [ Note: Such
expressions may be used as array bounds (8.3.4, 5.3.4), as bit-field
lengths (9.6), as enumerator initializers if the underlying type is
not fixed (7.2), as null pointer constants (4.10), and as alignments
(7.6.2). —end note ]
and or C++03 we can see this from the draft C++03 standard or the closest we can get same section paragraph 1 which says:
[...]An integral constant-expression can involve only literals of
arithmetic types (2.13, 3.9.1), enumerators, non-volatile const
variables or static data members of integral or enumeration types
initialized with constant expressions (8.5), non-type template
parameters of integral or enumeration types, and sizeof
expressions[...]
On rextester this code compiles fine for VC++, so this is no longer an issue in current versions this must have been a bug in 2008 that was eventually fixed. Also tested on webcompiler which was last updated December 3rd 2015 so this works on one of the latest releases as well.
One alternative may be to use a const int for example:
const int len = LEN2 ;
this will depends on whether Visual Studio 2008 considers enumerators to not be integer constant expressions or whether it is just in the context of array bounds, hopefully it is just the later.
C++98
As far as I can tell this also applies to C++98 as well, both gcc and clang allow this when using -std=c++98, there are no draft C++98 standards available to the public so I can confirm beyond that.