考虑以下计算数组长度的简单示例:
#include <iostream>
int a[] = {1, 2, 4};
int main(){ std::cout << sizeof(a)/sizeof(a[0]) << std::endl; }
演示
标准N4296::8.3.4/7 [dcl.array]
如果E是秩为i×j×。×k,则E出现在受到数组到指针转换的表达式中(4.2)转换为指向(n−1)维数组的指针秩j×。×k。
N4296::4.2/1 [conv.array]
类型为"N T数组"或"未知界数组"的左值或右值of T"可以转换为"pointer to T"类型的prvalue。结果是指向数组的第一个元素的指针。
那么,转换的主题是什么呢?看起来未求值的操作数不是主题。
http://coliru.stacked-crooked.com/a/36a1d02c7feff41c
我知道以下表达式,其中数组不会转换/衰减为指针。
- 在
sizeof
运算符中使用时:sizeof(array)
- 在addressof运算符中使用时:
&array
- 用于将引用绑定到数组时:
int (&ref)[3] = array;
- 在推导用于实例化模板的类型名称时
- 在
decltype
:decltype(array)
中使用时
我不知道是否有人能说出所有规则的名字,所以社区维基可能是合适的。
数组到指针的转换发生在以下上下文中。所有参考都是针对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.renterpret.cast]/1)
- 在转换为非引用类型的常量中([expr.const.cast]/1)
- 在条件运算符的第二个或第三个操作数中,在某些情况下([expr.cond])
- 在模板参数中,如果对应的(非类型)模板参数具有指向对象类型的指针([temp.arg.notype]/5)
数组到指针的转换不会发生在以下上下文中:
- 需要左值(或glvalue)时
- 通过一元
&
运算符([expr.unary.op]/3) - 在静态转换为引用类型([expr.static.cast]/2,[expr.静态.cast]/3)中
- 在重新解释强制转换为引用类型中([expr.renterpret.cast]/11)
- 在const强制转换为引用类型([expr.const.cast]/4)中
- 通过一元
- 绑定到对同一数组类型的引用时
- 在丢弃的值表达式([expr]/10)中
- 在
sizeof
([expr.sizeof]/4)的操作数中 - 当条件运算符的第二个和第三个操作数具有相同的数组类型并且都是相同值类别的glvalues时
- 在内置逗号运算符的任一操作数中
1这包括当用户定义的转换需要其中一种类型时,将T
的数组传递给期望cvT*
、cvTR
2这包括在if
语句等中发生的到bool
的上下文转换。
我所遵循的经验法则是"在表达式的任何部分生成可以存储在指针中但不能存储在数组中的值结果"。
例如;
- 表达式
array + 0
在进行加法之前将array
转换为指针,并给出作为指针的结果 - CCD_ 22在调用接受指针或数组(而不是引用)的函数CCD_ 24之前将CCD_
array[0]
不需要将array
转换为指针(但是编译器是自由的,因为它对该表达式的结果并没有影响)sizeof array
不会将array
转换为指针(因为它不会完全评估array
,仅评估其大小)- 表达式
p = array
将array
转换为指针和该值存储在p
中
我确信我遗漏了一些案例,但这个简单的规则相当有效。当然,它是基于对表达式的理解……
在您的示例代码中,a[0]
与*(a + 0)
相同,因此需要进行数组到指针的转换。请参阅内置下标运算符部分。