C ++指针 - 哪些是有效的

时间:2016-01-09 01:35:55

标签: c++ arrays pointers

我正在学习C ++,但我遇到了这个问题(真的很困扰我)......

假设:

int arr[] = {1, 2, 3, 4, 5};
int *p = arr;

哪些是合法的,哪些是非法的&这是什么意思?

  1. p[2]
  2. 2[p]
  3. p + 2
  4. arr[2]
  5. 2[arr]
  6. arr + 2
  7. 我不确定答案是什么,也不确定它们是什么意思。如果有人能向我解释,我将不胜感激

    由于

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]。虽然它在语法上是合法的,但它在语义上非常混乱,特别是对那些没有完全掌握指针的人。