2013-12-08 74 views
6

C++ 11代码:C&C++:数组的指针和地址有什么区别?

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; 

b的和c的值是相同的。

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

更新:我改变了数组大小为1〜3

+0

'auto'不能很好的使用指针,这种类型通常是不可信的。 – user2485710

+1

@ user2485710你能详细说明一下吗?任何参考/引用? – Domi

+0

'auto'在指针下工作得很好,不知道你有什么想法。 –

回答

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; 
+0

'sizeof'也会丢弃'const'部分为你的第二''cout'''变量。这就是为什么他们会产生相同的输出。 – user2485710

+0

@ user2485710:什么导致相同的输出?我的两条'cout'线输出两个不同的数字。 'const'根本不会出现在图片中。我无法将您的评论与我的帖子中的任何内容对齐。 –

+0

很棒的回答。突出一大堆我以前没有想过的概念!我可能应该更频繁地使用数组类型来支持指针类型! – Domi

6

在C++中的任何对象的身份由其类型及其地址确定。

在你的例子中,有两个不同的对象具有相同的地址:数组本身和数组的第一个元素。第一种是int[1],第二种是int。如果一个对象是另一个对象的子对象,那么两个不同的对象可以具有相同的地址,就像数组元素,类成员和类基类子对象一样。

如果你写你的例子会比较清楚:

int a[5]; 
int (*ptr_to_array)[5] = &a; 
int * ptr_to_array_element = &a[0]; 

但你已经采取的,对于阵列的ID表达a衰变到一个指向数组的第一个元素的事实优势,所以a有在您的上下文中与&a[0]的值相同。

+0

谢谢!我在你的代码中添加了一个稍微修改过的版本。 – Domi

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将跳过40个字节的10个整数值,而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); 
} 

所以你看,不同层次的指针变量的不规矩数组变量的方式做。