This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 113d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-03-20


734. Are unique addresses required for namespace-scope variables?

Section: 7.6.1.10  [expr.reinterpret.cast]     Status: CD2     Submitter: Daveed Vandevoorde     Date: 15 October, 2008

[Voted into WP at March, 2010 meeting.]

Consider the following example:

    static const char test1 = 'x';
    static const char test2 = 'x';
    bool f() {
        return &test1 != &test2;
    }

Is f() allowed to return false? Can a smart optimizer alias these two variables, taking advantage of the fact that they are const, initialized to the same value, and thus can never be different in a well-defined program?

The C++ Standard doesn't explicitly specify address allocation of objects except as members of arrays and classes, so the answer would appear to be that such an implementation would be conforming.

This situation appears to have been the inadvertent result of the resolution of issue 73. Prior to that change, 7.6.10 [expr.eq] said,

Two pointers of the same type compare equal if and only if they... both point to the same object...

That resolution introduced the current wording,

Two pointers of the same type compare equal if and only if... both represent the same address.

Notes from the March, 2009 meeting:

The CWG agreed that this aliasing should not be permitted in a conforming implementation.

Proposed resolution (November, 2009):

  1. Add the following as a new paragraph after 6.7.2 [intro.object] paragraph 5:

  2. Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two distinct objects that are neither bit-fields nor base class subobjects of zero size shall have distinct addresses [Footnote: Under the “as-if” rule an implementation is allowed to store two objects at the same machine address or not store an object at all if the program cannot observe the difference (6.9.1 [intro.execution]). —end footnote]. [Example:

      static const char test1 = 'x';
      static const char test2 = 'x';
      const bool b = &test1 != &test2;   // always true
    

    end example]

  3. Change 7.6.2.2 [expr.unary.op] paragraph 3 as follows:

  4. The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. In the first case, if the type of the expression is “T,” the type of the result is “pointer to T.” In particular, the address of an object of type “cv T” is “pointer to cv T,” with the same cv-qualifiers. For a qualified-id, if the member is a static member of type “T”, the type of the result is plain “pointer to T.” If the member is a non-static member of class C of type T, the type of the result is “pointer to member of class C of type T.” If the operand is a qualified-id naming a non-static member m of some class C with type T, the result has type “pointer to member of class C of type T” and is an rvalue designating C::m. Otherwise, if the type of the expression is T, the result has type “pointer to T” and is an rvalue that is the address of the designated object (6.7.1 [intro.memory]) or a pointer to the designated function. [Note: In particular, the address of an object of type “cv T” is “pointer to cv T,” with the same cv-qualification. —end note] [Example:...