user3663882
user3663882

Reputation: 7367

When are arrays converted to pointers?

Consider the following simple example computing lenght of an array:

#include <iostream>

int a[] = {1, 2, 4};

int main(){ std::cout << sizeof(a)/sizeof(a[0]) << std::endl; }

DEMO

The Standard N4296::8.3.4/7 [dcl.array]

If E is an n-dimensional array of rank i×j×. . .×k, then E appearing in an expression that is subject to the array-to-pointer conversion (4.2) is converted to a pointer to an (n−1)-dimensional array with rank j ×. . .×k.

N4296::4.2/1 [conv.array]

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

So what is the expressions which are the subject of the convertion? Looks like unevaluated operands are not the subject.

http://coliru.stacked-crooked.com/a/36a1d02c7feff41c

Upvotes: 0

Views: 231

Answers (4)

Brian Bi
Brian Bi

Reputation: 119467

I don't know if anyone can name all the rules off the top of their head, so a community wiki may be appropriate.

The array to pointer conversion occurs in the following contexts. All references are to the C++11 standard.

  • As part of an implicit conversion sequence selected by overload resolution1
  • As part of a standard conversion sequence, in contexts where one is allowed
    • When initializing an object of non-class type from an array ([dcl.init]/16)2
    • When assigning to an lvalue of non-class type from an array ([expr.ass]/3)
  • When a prvalue of pointer type is required as the operand to a built-in operator ([expr]/8)
    • When subscripting into the array ([expr.sub]/1)
    • When dereferencing a pointer ([expr.unary.op]/1)
    • With the unary + operator ([expr.unary.op]/7)
    • With the binary + operator ([expr.add]/1)
    • With the binary - operator ([expr.add]/2)
    • With the relational operators ([expr.rel]/1)
    • With the equality operators ([expr.eq]/1)
  • When calling a function, if an argument has array type and is passed to an ellipsis ([expr.call]/7)
  • When converting from a pointer to base class to a pointer to derived class ([expr.static.cast]/11)
  • In a reinterpret cast to a non-reference type ([expr.reinterpret.cast]/1)
  • In a const cast to a non-reference type ([expr.const.cast]/1)
  • In the second or third operand of the conditional operator, under certain circumstances ([expr.cond])
  • In a template argument, if the corresponding (non-type) template parameter has pointer to object type ([temp.arg.nontype]/5)

The array to pointer conversion does not occur in the following contexts:

  • Where an lvalue (or glvalue) is required
    • By the unary & operator ([expr.unary.op]/3)
    • In a static cast to reference type ([expr.static.cast]/2, [expr.static.cast]/3)
    • In a reinterpret cast to reference type ([expr.reinterpret.cast]/11)
    • In a const cast to reference type ([expr.const.cast]/4)
  • When binding to a reference to the same array type
  • In a discarded-value expression ([expr]/10)
  • In the operand to sizeof ([expr.sizeof]/4)
  • When the second and third operands to the conditional operator have the same array type and are both glvalues of the same value category
  • In either operand to the built-in comma operator

1 This includes the case where an array of T is passed to a function expecting cv T*, cv void*, or bool, when a user-defined conversion requires one of those types, etc.

2 This includes contextual conversions to bool as they occur in if statements and the like.

Upvotes: 2

Peter
Peter

Reputation: 36617

The rule of thumb I work by is "in any part of an expression that produces a value result that can be stored in a pointer but cannot be stored in an array".

So, for example;

  • The expression array + 0 converts array to a pointer before doing the addition, and gives a result that is a pointer.
  • f(array) converts array to a pointer before calling the function f() that accepts a pointer or an array (not a reference).
  • array[0] is not required to convert array to a pointer (but the compiler is free to, since it makes no difference on the result of that expression).
  • sizeof array does not convert array to a pointer (since it doesn't evaluate array at all, just its size)
  • The expression p = array converts array to a pointer and that value is stored in p

I'm sure there are some cases I've missed, but that simple rule works reasonably well. Of course, it is based on an understanding of what an expression is.....

Upvotes: 1

R Sahu
R Sahu

Reputation: 206717

I know of the following expressions in which an array is not converted/decayed to a pointer.

  1. When used in a sizeof operator: sizeof(array)
  2. When used in an addressof operator: &array
  3. When used to bind a reference to an array: int (&ref)[3] = array;.
  4. When deducing the typename to be used for instantiating templates.
  5. When used in decltype: decltype(array)

Upvotes: 3

Lingxi
Lingxi

Reputation: 14987

In your example code, a[0] is identical to *(a + 0), and is thus subject to array-to-pointer conversion. See the Built-in subscript operator section here.

Upvotes: -2

Related Questions