【发布时间】:2010-10-28 16:33:20
【问题描述】:
array[index] 和 index[array] 是编译器特性还是语言特性的可能性。第二个怎么可能?
【问题讨论】:
array[index] 和 index[array] 是编译器特性还是语言特性的可能性。第二个怎么可能?
【问题讨论】:
编译器会转
index[array]
进入
*(index + array)
使用正常的语法会变成这样
array[index]
进入
*(array + index)
因此您会看到两个表达式的计算结果相同。这适用于 C 和 C++。
【讨论】:
从 C 的早期开始,表达式a[i] 只是将 a[0] 的地址添加到 i(按 a[0] 的大小放大)然后取消引用。事实上,所有这些都是等价的:
a[i]
i[a]
*(a+i)
====
我唯一关心的是实际的取消引用。虽然它们都产生相同的地址,但如果
a和i的类型不同,则可能需要考虑取消引用。例如:
int i = 4;
long a[9];
long x = a[i]; //get the long at memory location X.
long x = i[a]; //get the int at memory location X?
我还没有实际测试过这种行为,但您可能需要注意这一点。如果它确实改变了被取消引用的内容,那么它也可能会导致对象数组出现各种问题。
====
更新:
您可以放心地忽略上面===== 行之间的位。我已经在 Cygwin 下用短和长测试了它,看起来还不错,所以我想我的担心是没有根据的,至少对于基本情况。我仍然不知道更复杂的会发生什么,因为这不是我想做的事情。
【讨论】:
正如 Matthew Wilson 在 Imperfect C++ 中所讨论的,这可用于强制 C++ 中的类型安全,方法是防止在定义下标运算符的类型实例中使用类似于 DIMENSION_OF() 的宏,如下所示:
#define DIMENSION_OF_UNSAFE(x) (sizeof(x) / sizeof((x)[0]))
#define DIMENSION_OF_SAFER(x) (sizeof(x) / sizeof(0[(x)]))
int ints[4];
DIMENSION_OF_UNSAFE(ints); // 4
DIMENSION_OF_SAFER(ints); // 4
std::vector v(4);
DIMENSION_OF_UNSAFE(v); // gives impl-defined value; v likely wrong
DIMENSION_OF_SAFER(v); // does not compile
处理指针还有更多内容,但这需要一些额外的模板智能。查看STLSoft 库中STLSOFT_NUM_ELEMENTS() 的实现,并在Imperfect C++ 的第14 章中阅读所有内容。
编辑:一些评论者建议实现不拒绝指针。它确实如此(以及用户定义的类型),如下面的程序所示。您可以通过未注释的第 16 行和第 18 行来验证这一点。(我只是在 Mac/GCC4 上这样做,它拒绝了这两种形式)。
#include <stlsoft/stlsoft.h>
#include <vector>
#include <stdio.h>
int main()
{
int ar[1];
int* p = ar;
std::vector<int> v(1);
printf("ar: %lu\n", STLSOFT_NUM_ELEMENTS(ar));
// printf("p: %lu\n", STLSOFT_NUM_ELEMENTS(p));
// printf("v: %lu\n", STLSOFT_NUM_ELEMENTS(v));
return 0;
}
【讨论】:
在 C 和 C++ 中(array 是指针或数组)它是一种语言特性:指针运算。将 a 或 b 为指针的操作 a[b] 转换为指针算术:*(a + b)。由于加法是对称的,因此重新排序不会改变含义。
现在,非指针存在差异。事实上,给定一个带有重载 operator[] 的类型 A,那么 a[4] 是一个有效的方法调用(将调用 A::operator),但相反的甚至不会编译。
【讨论】: