Possible Duplicate:
In C arrays why is this true? a[5] == 5[a]可能的重复:在C数组中为什么这是真的?[5]= = 5(一个)
Is the possibility of both array[index] and index[array] a compiler feature or a language feature. How is the second one possible?
是数组[index]和索引[array]作为编译器特性或语言特性的可能性。第二个怎么可能呢?
4 个解决方案
#1
24
The compiler will turn
编译器会
index[array]
into
成
*(index + array)
With the normal syntax it would turn
用正常的语法,它就会转动
array[index]
into
成
*(array + index)
and thus you see that both expressions evaluate to the same value. This holds for both C and C++.
因此你可以看到两个表达式的值是相同的。这对C和c++都适用。
#2
6
From the earliest days of C, the expression a[i]
was simply the address of a[0] added to i (scaled up by the size of a[0]) and then de-referenced. In fact, all these were equivalent:
从C的早期开始,表达式a[i]就是添加到i中的[0]的地址(按[0]的大小放大),然后再去引用。事实上,所有这些都是等价的:
a[i]
i[a]
*(a+i)
====
= = = =
The only thing I'd be concerned about is the actual de-referencing. Whilst they all produce the same address, de-referencing may be a concern if the types of
a
andi
are different.我唯一关心的是实际的去引用。虽然它们都产生相同的地址,但是如果a和i的类型不同,那么反引用可能是一个问题。
For example:
例如:
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?
I haven't actually tested that behavior but it's something you may want to watch out for. If it does change what gets de-referenced, it's likely to cause all sorts of problems with arrays of objects as well.
我还没有测试过这种行为,但是你可能需要注意。如果它确实改变了被取消引用的内容,那么它很可能也会导致对象数组的各种问题。
====
= = = =
Update:
更新:
You can probably safely ignore the bit above between the =====
lines. I've tested it under Cygwin with a short and a long and it seems okay, so I guess my fears were unfounded, at least for the basic cases. I still have no idea what happens with more complicated ones because it's not something I'm ever likely to want to do.
您可以安全地忽略上面的===== ===行之间的位。我已经在Cygwin下测试过了,它有短的和长的,看起来还可以,所以我想我的担心是没有根据的,至少在基本情况下是这样的。我仍然不知道更复杂的情况会发生什么,因为这不是我可能想要做的事情。
#3
5
As Matthew Wilson discusses in Imperfect C++, this can be used to enforce type safety in C++, by preventing use of DIMENSION_OF()
-like macros with instances of types that define the subscript operator, as in:
正如Matthew Wilson在“不完美的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
There's more to this, for dealing with pointers, but that requires some additional template smarts. Check out the implementation of STLSOFT_NUM_ELEMENTS()
in the STLSoft libraries, and read about it all in chapter 14 of Imperfect C++.
这里还有更多的内容,用于处理指针,但这需要一些额外的模板技巧。在STLSoft库中查看STLSOFT_NUM_ELEMENTS()的实现,并在不完美c++的第14章中阅读相关内容。
edit: some of the commenters suggest that the implementation does not reject pointers. It does (as well as user-defined types), as illustrated by the following program. You can verify this by uncommented lines 16 and 18. (I just did this on Mac/GCC4, and it rejects both forms).
编辑:一些评论者建议实现不拒绝指针。它可以(以及用户定义的类型),如下面的程序所示。您可以通过未注释的第16和18行来验证这一点。(我刚刚在Mac/GCC4上做了这个,它拒绝这两种形式)。
1
2 #include <stlsoft/stlsoft.h>
3
4 #include <vector>
5
6 #include <stdio.h>
7
8 int main()
9 {
10 int ar[1];
11 int* p = ar;
12 std::vector<int> v(1);
13
14 printf("ar: %lu\n", STLSOFT_NUM_ELEMENTS(ar));
15
16 // printf("p: %lu\n", STLSOFT_NUM_ELEMENTS(p));
17
18 // printf("v: %lu\n", STLSOFT_NUM_ELEMENTS(v));
19
20 return 0;
21 }
22
#4
0
In C and C++ (with array being a pointer or array) it is a language feature: pointer arithmetic. The operation a[b] where either a or b is a pointer is converted into pointer arithmetic: *(a + b). With addition being symetrical, reordering does not change meaning.
在C和c++中(数组是指针或数组),它是一种语言特性:指针算法。将a或b为指针的操作a[b]转换为指针算法:*(a + b).加是对称的,重新排序不会改变意义。
Now, there are differences for non-pointers. In fact given a type A with overloaded operator[], then a[4] is a valid method call (will call A::operator ) but the opposite will not even compile.
非指针有区别。实际上,给定一个具有重载操作符[]的a类型,[4]是一个有效的方法调用(将调用a:::操作符),但相反的调用甚至不会编译。
#1
24
The compiler will turn
编译器会
index[array]
into
成
*(index + array)
With the normal syntax it would turn
用正常的语法,它就会转动
array[index]
into
成
*(array + index)
and thus you see that both expressions evaluate to the same value. This holds for both C and C++.
因此你可以看到两个表达式的值是相同的。这对C和c++都适用。
#2
6
From the earliest days of C, the expression a[i]
was simply the address of a[0] added to i (scaled up by the size of a[0]) and then de-referenced. In fact, all these were equivalent:
从C的早期开始,表达式a[i]就是添加到i中的[0]的地址(按[0]的大小放大),然后再去引用。事实上,所有这些都是等价的:
a[i]
i[a]
*(a+i)
====
= = = =
The only thing I'd be concerned about is the actual de-referencing. Whilst they all produce the same address, de-referencing may be a concern if the types of
a
andi
are different.我唯一关心的是实际的去引用。虽然它们都产生相同的地址,但是如果a和i的类型不同,那么反引用可能是一个问题。
For example:
例如:
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?
I haven't actually tested that behavior but it's something you may want to watch out for. If it does change what gets de-referenced, it's likely to cause all sorts of problems with arrays of objects as well.
我还没有测试过这种行为,但是你可能需要注意。如果它确实改变了被取消引用的内容,那么它很可能也会导致对象数组的各种问题。
====
= = = =
Update:
更新:
You can probably safely ignore the bit above between the =====
lines. I've tested it under Cygwin with a short and a long and it seems okay, so I guess my fears were unfounded, at least for the basic cases. I still have no idea what happens with more complicated ones because it's not something I'm ever likely to want to do.
您可以安全地忽略上面的===== ===行之间的位。我已经在Cygwin下测试过了,它有短的和长的,看起来还可以,所以我想我的担心是没有根据的,至少在基本情况下是这样的。我仍然不知道更复杂的情况会发生什么,因为这不是我可能想要做的事情。
#3
5
As Matthew Wilson discusses in Imperfect C++, this can be used to enforce type safety in C++, by preventing use of DIMENSION_OF()
-like macros with instances of types that define the subscript operator, as in:
正如Matthew Wilson在“不完美的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
There's more to this, for dealing with pointers, but that requires some additional template smarts. Check out the implementation of STLSOFT_NUM_ELEMENTS()
in the STLSoft libraries, and read about it all in chapter 14 of Imperfect C++.
这里还有更多的内容,用于处理指针,但这需要一些额外的模板技巧。在STLSoft库中查看STLSOFT_NUM_ELEMENTS()的实现,并在不完美c++的第14章中阅读相关内容。
edit: some of the commenters suggest that the implementation does not reject pointers. It does (as well as user-defined types), as illustrated by the following program. You can verify this by uncommented lines 16 and 18. (I just did this on Mac/GCC4, and it rejects both forms).
编辑:一些评论者建议实现不拒绝指针。它可以(以及用户定义的类型),如下面的程序所示。您可以通过未注释的第16和18行来验证这一点。(我刚刚在Mac/GCC4上做了这个,它拒绝这两种形式)。
1
2 #include <stlsoft/stlsoft.h>
3
4 #include <vector>
5
6 #include <stdio.h>
7
8 int main()
9 {
10 int ar[1];
11 int* p = ar;
12 std::vector<int> v(1);
13
14 printf("ar: %lu\n", STLSOFT_NUM_ELEMENTS(ar));
15
16 // printf("p: %lu\n", STLSOFT_NUM_ELEMENTS(p));
17
18 // printf("v: %lu\n", STLSOFT_NUM_ELEMENTS(v));
19
20 return 0;
21 }
22
#4
0
In C and C++ (with array being a pointer or array) it is a language feature: pointer arithmetic. The operation a[b] where either a or b is a pointer is converted into pointer arithmetic: *(a + b). With addition being symetrical, reordering does not change meaning.
在C和c++中(数组是指针或数组),它是一种语言特性:指针算法。将a或b为指针的操作a[b]转换为指针算法:*(a + b).加是对称的,重新排序不会改变意义。
Now, there are differences for non-pointers. In fact given a type A with overloaded operator[], then a[4] is a valid method call (will call A::operator ) but the opposite will not even compile.
非指针有区别。实际上,给定一个具有重载操作符[]的a类型,[4]是一个有效的方法调用(将调用a:::操作符),但相反的调用甚至不会编译。