Max Maier
Max Maier

Reputation: 1045

Implicit Pointer-To-Const-T conversion

I was wondering if the implicit conversion to a pointer to a const data type is somewhere defined in the C11 standard:

T x;
const T *p = &x;

A pointer to an object of type T is implicitly converted into a pointer to an object of type const T. Is this implicit conversion somewhere defined in the C11 standard? (I know that it makes sense to allow this and how useful it is. I'm just curious to know where it is defined in the standard)

Furthermore, is an implicit conversion from type T** to const T** forbidden according to C11?

T *p;
const T **pp = &p;

This is a well known problematic part and therefore GCC and LLVM/clang raise a warning. Still I'm wondering if this is allowed according to the C11 standard or not. I only found in §6.5.16.1P6 a comment that this should be a constraint violation. However, I do not see which constraint should be violated. Again I know that this should be prohibited and that this implicit conversion can lead to subtle problems. I'm just curious to know if this is (un)defined behaviour according to C11.

Again, my two questions are not about if this is good or not (which is answered multiple times here) but how/where the C11 standard defines this.


Just for the sake of completeness here is a link to why the second example is problematic: http://c-faq.com/ansi/constmismatch.html

Upvotes: 2

Views: 312

Answers (1)

Petr Skocik
Petr Skocik

Reputation: 60068

A pointer to an object of type T is implicitely converted into a pointer to an object of type const-T. Is this implicit conversion somewhere defined in the C11 standard?

Yes. This implicit conversion is mandated by the standard.

Paragraph 3 of section 6.5.4 Cast Operators says that

Conversions that involve pointers, other than where permitted by the constraints of 6.5.16.1, shall be specified by means of an explicit cast.

and the referenced 6.5.16.1 under point 3 says:

the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;

Therefore the implicit conversion for const T *p = &x; holds because you're only adding qualifiers, not removing them.

const T **pp = &p; doesn't fall under this, so you need an explicit cast (C++ would allow const T*const*pp = &p; (the second const is needed) but C still wouldn't.)

The pointer conversion through an explicit cast isn't a problem as far as UB is concerned as long as the alignments match (which for pointers to differently qualified types they will) because 6.3.2.3p7 guarantees that:

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned68) for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

but you need to be mindful of accesses/dereferences which will be governed by the strict aliasing rule:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)

a type compatible with the effective type of the object, a qualified version of a type compatible with the effective type of the object, a type that is the signed or unsigned type corresponding to the effective type of the object, a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object, an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or a character type.

Upvotes: 3

Related Questions