C+数组[index] vs索引[array] [duplicate]

时间:2022-07-27 22:30:44

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 and i 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 and i 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:::操作符),但相反的调用甚至不会编译。