我正在学习C ++,但我遇到了这个问题(真的很困扰我)......
假设:
int arr[] = {1, 2, 3, 4, 5};
int *p = arr;
哪些是合法的,哪些是非法的&这是什么意思?
p[2]
2[p]
p + 2
arr[2]
2[arr]
arr + 2
我不确定答案是什么,也不确定它们是什么意思。如果有人能向我解释,我将不胜感激
由于
答案 0 :(得分:4)
根据标准,所有6个表达式都有效:
5.2.1 / 1 后缀表达式后跟方括号中的表达式是后缀表达式。其中一个表达应该有 类型“T的数组”或“指向T的指针”,另一个应具有 无范围枚举或整数类型。结果是“T”类型 类型“T”应是完全定义的对象类型。 表达 E1 [E2]与*((E1)+(E2))
相同(根据定义)
所有subscipting表达式(即后跟方括号,即1,2,4和5)是通过解引用指针算法获得的指针获得的整数。
例如:
p[2]
相当于*(p+2)
。由于p是一个指向整数的指针,这将返回数组中的第3个整数(下标以0开头),因此为3.
2[p]
看起来很奇怪。我不推荐这种表示法,但它也等同于*(2+p)
。由于p是指向整数的指针,因此2 + p也将引用数组中的第3个整数。
剩下的两个表达式(即3和6)使用指针算法返回指向整数的指针。它们都将返回数组中第3个元素的地址。
这是online demo。
答案 1 :(得分:0)
正如评论中所述,p[i]
和*(p + i)
意味着同样的事情。这有时被称为“数组指针二元性”。
所有六种表达方式都有效,但其中两种表达方式与其他四种表达方式有不同的含义。
int arr[] = {1, 2, 3, 4, 5}; int *p = arr;
我们从数组arr开始。标签arr
指向数组中第一个元素的内存地址。 (*实际上,它更复杂,但这对于这次讨论并不重要。)
然后,我们设置p(一个int *,因此,一个地址)等于arr。所以p和arr指向相同的内存位置。
1. p[2] 2. 2[p] 4. arr[2] 5. 2[arr]
这四个表示数组值(指针取消引用),它们都表示相同的值:*(p + 2)
。 (对于1和2,因为p == arr,它们给出与1和2相同的值。)
3. p + 2 6. arr + 2
这两个代表特定的指针算术。但是因为你没有取消引用任何东西,你得到一个内存地址,而不是一个值。
如果您尝试编译此程序,您可以更清楚地看到:
#include <stdio.h>
int main(void)
{
int arr[] = { 1, 2, 3, 4, 5 };
int *p = arr;
printf("1: %d\n", p[2]);
printf("2: %d\n", 2[p]);
printf("3: %d\n", p + 2);
printf("4: %d\n", arr[2]);
printf("5: %d\n", 2[arr]);
printf("6: %d\n", arr + 2);
}
你收到这些警告:
foo.c:11:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("3: %d\n", p + 2);
~~ ^~~~~
foo.c:14:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("6: %d\n", arr + 2);
~~ ^~~~~~~
2 warnings generated.
这个输出:
1: 3
2: 3
3: 1499322968
4: 3
5: 3
6: 1499322968
注意警告(以及3和6的结果值):指针算术会产生指针,而不是值。另请注意,它的内存地址相同。如果你试图访问*(p + 2)或*(arr + 2),你会得到3。
现在,作为一种练习,你可能不想写2 [arr]或2 [p]。虽然它在语法上是合法的,但它在语义上非常混乱,特别是对那些没有完全掌握指针的人。