2010-06-01 43 views
8

thể trùng lặp:
casting char[][] to char** causes segfault?int ** vs int [ROWS] [COLS]

Tôi có một mảng 2D tuyên bố như thế này:

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

Bây giờ nếu Tôi làm:

int ** ptr=(int**) arr; 

và:

cout<<**ptr; 

Tôi nhận được một lỗi phân khúc (sử dụng g ++ - 4.0).

Tại sao vậy? Không nên in giá trị 1 (bằng arr[0][0])?

+3

Tôi nghĩ rằng có một quy tắc tuyệt vời trong C++: "Nếu bạn có để cast, bạn không thể đủ khả năng đó" http://blogs.msdn.com/b/oldnewthing/archive/2009/10/23/9911891.aspx – SergGr

Trả lời

1

Bạn đang cố chỉ định một biến con trỏ kép cho một mảng ... điều này đã được đề cập đầy đủ, xem here để biết thông tin về điều này. Hơn nữa, kể từ khi bạn tuyên bố

 
int arr[2][2] = ...; 

và sau đó cố gắng gán arr đến một con trỏ đôi

 
int ** ptr = ... ; 

được đảm bảo để không làm việc, do đó một lỗi segmentation.Hơn nữa, tuyên bố đó int ** ptr=(int**) arr; thực sự là truyền nhập một loại (tức là [] []) sang một loại khác (tức là **) mặc dù chúng thuộc loại 'int'. Cả hai đều khác nhau và trình biên dịch sẽ giải thích rằng rất khác nhau ...

Bạn có thể làm theo cách này:

 
int *ptr = &arr; 

Bây giờ *(ptr + 1) sẽ đề cập đến hàng 0'th, *(ptr + 2) sẽ giới thiệu đến 1 'st hàng và như vậy. Các chỉ onus trên bạn là không overstep các dấu hiệu của nơi arr được sử dụng nếu không một tràn có thể xảy ra hoặc thậm chí một lỗi phân đoạn ...

0

Hãy thử

int *ptr = arr; 

More Giải thích:

Bạn nên gán một địa chỉ để con trỏ, vì vậy nó có thể được derefenced (i có nghĩa là nhà điều hành *). Những gì bạn làm là, chỉ ptr vào ô nhớ có địa chỉ a [0] [0]. Vì vậy, bạn nhận được một lỗi phân đoạn.

5

Bạn không thể truyền mảng tuyến tính sang loại con trỏ tới con trỏ, vì int** không giữ cùng dữ liệu int[][]. Việc giữ con trỏ đầu tiên đến điểm. Cái thứ hai giữ một chuỗi các int, trong bộ nhớ tuyến tính.

+0

Vâng, bạn "có thể", như OP trình bày. Bạn chỉ cần làm một reinterpret_cast, mà OP vô tình đã làm bởi vì họ đang sử dụng phôi kiểu c. Như với tất cả các phôi như vậy, kết quả của việc truy cập con trỏ mới là UB. Đạo đức OP nên nhận được là: sử dụng C++ phôi trong C++. –

1

Không, int ** là một con trỏ trỏ tới một con trỏ, nhưng mảng 2-D là một mảng các mảng và &(arr[0][0]) là một con trỏ tới một int.

Tôi tin rằng bạn nên làm điều này:

int *ptr = arr; 
cout<<*ptr; 

hay này:

int *ptr = &arr[0][0]; 
cout<<*ptr; 
2

Những gì bạn làm bây giờ có nghĩa là tạo các mảng của con trỏ nơi mỗi con trỏ là đúc một cách rõ ràng. Do đó, bạn sẽ có một loạt các con trỏ như (0x00001, 0x00002, 0x00003 and 0x00004).

Khi không tham gia, con trỏ này gây ra sự phân đoạn của bạn.

0

int arr[2][2] không phải là mảng mảng - nó là một mảng 2d duy nhất. Trong trí nhớ, nó là không thể phân biệt từ int arr[4]

gì bạn thực sự muốn là

int (*ptr)[2] = arr; 
+0

Chính thức, nó * là * một mảng các mảng. Nhưng có, vì các mảng được đặt ra một cách liên tục mà không có padding được cho phép, một 'int [2] [2]' thực sự được đặt chính xác như một 'int [4]' trong bộ nhớ. – caf