数组何时转换为指针?

时间:2015-04-05 06:36:57

标签: c++ arrays pointers c++14

考虑以下简单示例计算数组的长度:

#include <iostream>

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

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

DEMO

标准N4296::8.3.4/7 [dcl.array]

  

如果E是秩i×j×的n维阵列。 。 。×k,然后E出现   在 的表达式中,受到数组到指针的转换   (4.2)转换为指向(n-1)维数组的指针   等级j×。 。 。×K

N4296::4.2/1 [conv.array]

  

“N T数组”或“未知数组的数组”的左值或右值   T“可以转换为”指向T“的prvalue类型。结果   是指向数组第一个元素的指针。

那么转换的主题是什么表达式?看起来未评估的操作数不是主题。

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

4 个答案:

答案 0 :(得分:3)

我知道以下表达式,其中数组未转换/衰减为指针。

  1. sizeof运算符中使用时:sizeof(array)
  2. 在地址运营商中使用时:&array
  3. 用于绑定对数组的引用时:int (&ref)[3] = array;
  4. 在推断用于实例化模板的类型名称时。
  5. decltype中使用时:decltype(array)

答案 1 :(得分:2)

我不知道是否有人可以将所有规则排除在首位,因此社区维基可能是合适的。

数组到指针的转换发生在以下上下文中。所有引用都是针对C ++ 11标准的。

  • 作为重载决策 1
  • 选择的隐式转换序列的一部分
  • 作为标准转换序列的一部分,在允许一个转换序列的上下文中
    • 从数组初始化非类型对象时([dcl.init] / 16) 2
    • 从数组([expr.ass] / 3)分配非类型的左值时
  • 当需要指针类型的prvalue作为内置运算符的操作数([expr] / 8)时
    • 订阅数组时([expr.sub] / 1)
    • 取消引用指针([expr.unary.op] / 1)
    • 使用一元+运算符([expr.unary.op] / 7)
    • 使用二进制+运算符([expr.add] / 1)
    • 使用二进制-运算符([expr.add] / 2)
    • 使用关系运算符([expr.rel] / 1)
    • 使用相等运算符([expr.eq] / 1)
  • 调用函数时,如果参数具有数组类型并传递给省略号([expr.call] / 7)
  • 从指向基类的指针转换为指向派生类的指针([expr.static.cast] / 11)
  • 重新解释转换为非引用类型([expr.reinterpret.cast] / 1)
  • 在const转换为非引用类型([expr.const.cast] / 1)
  • 在条件运算符的第二个或第三个操作数中,在某些情况下([expr.cond])
  • 在模板参数中,如果相应的(非类型)模板参数具有指向对象类型的指针([temp.arg.nontype] / 5)

在以下上下文中不会发生数组到指针的转换:

  • 需要左值(或右值)
    • 由一元&运算符([expr.unary.op] / 3)
    • 在静态转换为引用类型([expr.static.cast] / 2,[expr.static.cast] / 3)
    • 重新解释转换为引用类型([expr.reinterpret.cast] / 11)
    • 在const转换为引用类型([expr.const.cast] / 4)
  • 绑定到对同一数组类型的引用时
  • 在废弃值表达式([expr] / 10)
  • sizeof([expr.sizeof] / 4)
  • 的操作数中
  • 当条件运算符的第二个和第三个操作数具有相同的数组类型且都是相同值类别的glvalues时
  • 在内置逗号运算符的任一操作数中

1 这包括将T数组传递给期望 cv T* cv的函数的情况 void*bool,当用户定义的转换需要其中一种类型时,等。

2 这包括在bool语句中出现的if的上下文转换等。

答案 2 :(得分:1)

我工作的经验法则是&#34;在表达式的任何部分中产生一个值存储在指针中但不能存储在数组中的值结果&#34;。

所以,例如;

  • 表达式array + 0在执行添加之前将array转换为指针,并给出一个指针结果。
  • f(array)在调用接受指针或数组(不是引用)的函数array之前将f()转换为指针。
  • array[0]不需要将array转换为指针(但是 编译器是免费的,因为它对该表达式的结果没有影响。)
  • sizeof array不会将array转换为指针(因为它没有 完全评估array,只评估其大小)
  • 表达式p = arrayarray转换为指针和该值 存储在p

我确定在某些情况下我错过了,但这个简单的规则运作得相当好。当然,它是基于对表达式的理解.....

答案 3 :(得分:-2)

在您的示例代码中,a[0]*(a + 0)相同,因此需要进行数组到指针的转换。请参阅内置下标运算符部分here