2013-12-08 18 views
6

C++ 11 mã:C & C++: Sự khác biệt giữa mảng con trỏ tới và địa chỉ của mảng là gì?

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

C mã:

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

Các giá trị của bc đều giống nhau.

Sự khác nhau giữa bc là gì? Tại sao họ không cùng loại?

UPDATE: Tôi đã thay đổi kích thước mảng từ 1 đến 3.

+0

'tự động' không phát đẹp với con trỏ, thường không đáng tin cậy với loại loại này. – user2485710

+1

@ user2485710 Bạn có thể giải thích về điều đó không? Bất kỳ tài liệu tham khảo/trích dẫn nào? – Domi

+0

'auto' hoạt động tốt với con trỏ, không có đầu mối nào bạn có ý tưởng đó. –

Trả lời

7

Nhà điều hành sizeof nên hành xử khác nhau, cho một, đặc biệt là nếu bạn thay đổi tuyên bố a một số khác nhau của các số nguyên, chẳng hạn như 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; 
} 

Đối với tôi, bản in này:

4 
28 

Đó là bởi vì hai con trỏ là các loại rất khác nhau. Một là một con trỏ đến số nguyên, và cái còn lại là một con trỏ tới một mảng gồm 7 số nguyên.

Loại thứ hai thực sự có loại con trỏ tới mảng. Nếu bạn dereference nó, chắc chắn, nó sẽ decay to a pointer trong hầu hết trường hợp, nhưng nó không thực sự là một con trỏ đến con trỏ đến int. Cái đầu tiên là con trỏ-to-int vì phân rã đã xảy ra ở bài tập.

Những nơi khác nó sẽ hiển thị là nếu bạn thực sự đã có hai biến kiểu con trỏ-to-mảng, và cố gắng gán một đến khác:

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

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

    aa = bb; 

    return 0; 
} 

này tôi kiếm được thông báo lỗi:

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

Ví dụ này, tuy nhiên, công trình, bởi vì dereferencing bb cho phép nó phân rã để con trỏ-to-int:

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

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

    aa = *bb; 

    return 0; 
} 

Lưu ý rằng sự phân rã không xảy ra ở phía bên trái của bài tập. Điều này không làm việc:

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

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

    *aa = *bb; 

    return 0; 
} 

Điều đó giúp bạn điều này:

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' cũng loại bỏ phần' const' cho 'cout' thứ hai bằng' c' biến. Đó là lý do tại sao chúng dẫn đến kết quả giống nhau. – user2485710

+0

@ user2485710: Kết quả đầu ra giống hệt nhau là gì? Hai dòng 'cout' của tôi xuất ra hai số khác nhau. 'const' không đi vào bức tranh chút nào. Tôi không thể sắp xếp nhận xét của bạn với bất kỳ điều gì trong bài đăng của tôi. –

+0

Câu trả lời hay. Nổi bật một loạt các khái niệm mà tôi đã không đưa ra nhiều suy nghĩ, trước đây! Tôi có lẽ nên sử dụng các loại mảng có lợi cho các loại con trỏ thường xuyên hơn! – Domi

6

Danh tính của bất kỳ đối tượng trong C++ được xác định bởi cặp của nó loạiđịa chỉ của nó.

Có hai đối tượng riêng biệt với cùng một địa chỉ trong ví dụ của bạn: Bản thân mảng và phần tử đầu tiên của mảng. Loại đầu tiên có loại int[1], loại thứ hai có loại int. Hai đối tượng riêng biệt có thể có cùng một địa chỉ nếu một là một subobject của khác, như là trường hợp cho các phần tử mảng, các thành viên lớp và các lớp con cơ sở lớp.

dụ của bạn sẽ được rõ ràng hơn nếu bạn đã viết:

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

Nhưng bạn đã bị lợi dụng thực tế là id thể hiện a cho mảng phân rã đến một con trỏ đến phần tử đầu tiên của mảng, vì vậy a có có cùng giá trị với &a[0] trong ngữ cảnh của bạn.

+0

Cảm ơn! Tôi đã thêm một phiên bản mã sửa đổi nhỏ vào câu hỏi của tôi. – Domi

1

Hãy xem xét ví dụ sau:

#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 
     ); 
} 

Bạn sẽ thấy rằng tất cả các giá trị 5 in trong trường hợp đầu tiên đều bình đẳng. Bởi vì chúng trỏ đến cùng một vị trí ban đầu.

Nhưng chỉ khi bạn tăng chúng lên 1 bạn thấy rằng các con trỏ khác nhau hiện đang nhảy (điểm) đến các vị trí khác nhau. Điều này là do myArray[0][0][0] + 1 sẽ nhảy qua 10 giá trị số nguyên là 40 byte, trong khi myArray[0][0] + 1 sẽ nhảy bởi 100 giá trị số nguyên, tức là 400 byte. Tương tự, myArray[0] + 1 nhảy 1000 giá trị số nguyên hoặc 4000 byte.

Vì vậy, các giá trị phụ thuộc vào mức độ cấp độ con trỏ mà bạn đang đề cập đến.

Nhưng bây giờ, nếu tôi sử dụng con trỏ để chỉ tất cả trong số họ:

#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); 
} 

Vì vậy, bạn thấy, mức độ khác nhau của các biến con trỏ không hành xử theo cách biến mảng không.

Các vấn đề liên quan