C& C ++:指针到数组的地址有什么区别?

时间:2013-12-08 14:49:54

标签: c++ c arrays pointers auto

C ++ 11代码:

int a[3];
auto b = a;       // b is of type int*
auto c = &a;      // c is of type int(*)[1]

C代码:

int a[3];
int *b = a;
int (*c)[3] = &a;

bc的值相同。

bc之间有什么区别?为什么他们不是同一类型?

更新:我将数组大小从1更改为3.

3 个答案:

答案 0 :(得分:7)

sizeof运算符的行为应该不同,特别是如果您将a的声明更改为不同的整数,例如int a[7]

int main()
{
    int a[7];

    auto b = a;
    auto c = &a;

    std::cout << sizeof(*b) << std::endl;  // outputs sizeof(int)
    std::cout << sizeof(*c) << std::endl;  // outputs sizeof(int[7])

    return 0;
}

对我来说,打印:

4
28

那是因为两个指针的类型非常不同。一个是指向整数的指针,另一个是指向7个整数数组的指针。

第二个确实有指针到数组的类型。如果你取消引用它,当然,在大多数情况下它会decay to a pointer,但它实际上并不是指向int的指针。第一个是指向int的指针,因为在赋值时发生了衰减。

它会显示的其他地方是你确实有两个指针到数组类型的变量,并尝试将一个变量分配给另一个:

int main()
{
    int a[7];
    int b[9];

    auto aa = &a;
    auto bb = &b;

    aa = bb;

    return 0;
}

这使我收到错误消息:

xx.cpp: In function ‘int main()’:
xx.cpp:14:8: error: cannot convert ‘int (*)[9]’ to ‘int (*)[7]’ in assignment
     aa = bb;

然而,这个例子有效,因为解除引用bb允许它衰减到指向int的指针:

int main()
{
    int a;
    int b[9];

    auto aa = &a;
    auto bb = &b;

    aa = *bb;

    return 0;
}

请注意,衰减不会发生在作业的左侧。这不起作用:

int main()
{
    int a[7];
    int b[9];

    auto aa = &a;
    auto bb = &b;

    *aa = *bb;

    return 0;
}

它为你赢得了这个:

xx2.cpp: In function ‘int main()’:
xx2.cpp:14:9: error: incompatible types in assignment of ‘int [9]’ to ‘int [7]’
     *aa = *bb;

答案 1 :(得分:6)

C ++中任何对象的标识由其类型及其地址决定。

在您的示例中,有两个不同的对象具有相同的地址:数组本身,以及数组的第一个元素。第一个类型为int[1],第二个类型为int。如果一个是另一个的子对象,则两个不同的对象可以具有相同的地址,如数组元素,类成员和类基础子对象的情况。

如果你写了:

你的例子会更清楚
int a[5];
int (*ptr_to_array)[5] = &a;
int * ptr_to_array_element = &a[0];

但是你已经利用了这样一个事实,即数组的id-expression a衰减为指向数组第一个元素的指针,因此a具有与&a[0]相同的值在你的背景下。

答案 2 :(得分:1)

考虑这个例子:

#include<stdio.h>

int main()
{
    int myArray[10][10][10][10]; //A 4 Dimentional array;

    //THESE WILL ALL PRINT THE SAME VALUE
    printf("%d, %d, %d, %d, %d\n",
            myArray,
            myArray[0],
            myArray[0][0],
            myArray[0][0][0],
            &myArray[0][0][0][0]
          );

    //NOW SEE WHAT VALUES YOU GET AFTER ADDING 1 TO EACH OF THESE POINTERS
    printf("%d, %d, %d, %d, %d\n",
            myArray+1,
            myArray[0]+1,
            myArray[0][0]+1,
            myArray[0][0][0]+1,
            &myArray[0][0][0][0]+1
          );
}

您会发现在第一种情况下打印的所有5个值都是相同的。因为它们指向相同的初始位置。

但是当你将它们递增1时,你会看到不同的指针现在跳转(指向)到不同的位置。这是因为myArray[0][0][0] + 1将跳过10个整数值,即40个字节,而myArray[0][0] + 1将跳过100个整数值,即400个字节。类似地,myArray[0] + 1跳过1000个整数值或4000个字节。

因此,值取决于您所指的指针级别。

但现在,如果我使用指针来引用所有这些:

#include<stdio.h>

int main()
{
    int myArray[10][10][10][10]; //A 4 Dimentional array;

            int * ptr1 = myArray[10][10][10];
            int ** ptr2 = myArray[10][10];
            int *** ptr3 = myArray[10];
            int **** ptr4 = myArray;

    //THESE WILL ALL PRINT THE SAME VALUE
    printf("%u, %u, %u, %u\n", ptr1, ptr2, ptr3, ptr4);

    //THESE ALSO PRINT SAME VALUES!!
    printf("%d, %d, %d, %d\n",ptr1+1,ptr2+1,ptr3+1,ptr4+1);
}

所以你看,不同级别的指针变量的行为与数组变量不同。