2008-12-23 31 views
8

Nếu tôi có thể tạo một tập tin:Không thể chuyển đổi (*) [] để **

test.cpp:

void f(double **a) { 

} 

int main() { 
    double var[4][2]; 
    f(var); 
} 

Và sau đó chạy: g ++ test.cpp -o test

Tôi nhận được

test.cpp: In function `int main()': 
test.cpp:8: error: cannot convert `double (*)[2]' to `double**' for argument `1' 
to `void f(double**)' 

Tại sao tôi không thể làm điều này?

Không phải là var kép [4] [2] là giống như làm đôi ** var và sau đó phân bổ bộ nhớ?

Trả lời

17

C++ strings: [] vs. *

Nhìn vào Excursion: Mảng đa chiều trong đó mô tả cách bạn vượt qua mảng đa chiều để các chức năng như các đối số. Về cơ bản, bạn muốn thay đổi mã của mình thành mã này:

// same as void f(double (*a)[2]) { 
void f(double a[][2]) { 

} 

int main() { 
    // note. this is not a pointer to a pointer, 
    // but an array of arrays (4 arrays of type double[2]) 
    double var[4][2]; 

    // trying to pass it by value will pass a pointer to its 
    // first element 
    f(var); 
} 

Tất cả các kích thước cuối cùng phải được gọi là hàm được gọi. Nếu không lập chỉ mục mảng, trình biên dịch sẽ không thể tính toán khoảng cách chính xác cho các giá trị vào mảng của bạn (một [1] cách sizeof(double[2]) byte từ [0]).

Bạn dường như muốn có thể chấp nhận mảng mà không biết kích thước của các thứ nguyên. Bạn có thể sử dụng các mẫu cho việc này:

template<std::size_t N> 
void f(double a[][N]) { 
    // N == 2 for us 
} 

int main() { 
    double var[4][2]; 
    f(var); 
} 

Trình biên dịch sẽ tạo một bản sao của (thuyết minh) rằng mẫu cho mỗi giá trị của N sử dụng với các chức năng, tính năng tự động suy ra như N. đúng

+0

Cảm ơn bạn, tôi thích liên kết bạn đã cung cấp cho tôi vì tôi có thể hiểu sâu hơn từ đó. Và cũng là ví dụ mẫu bạn đã cho tôi. nhân đôi [] [2] chính xác là những gì tôi cần trong chương trình cụ thể của tôi. – Ezequiel

0

Vấn đề là rằng một đôi ** là một con trỏ đến một con trỏ. Hàm 'f' của bạn muốn được chuyển địa chỉ của một con trỏ tới một dấu gấp đôi. Nếu bạn gọi f (var), tốt, chính xác thì bạn nghĩ con trỏ đó ở đâu? Nó không tồn tại.

này sẽ làm việc:

double *tmp = (double *) var; 
f (&tmp); 

Ngoài ra, nó sẽ làm việc để thay đổi định nghĩa của f:

void f (double a[4][2]) { } 

Bây giờ e mất một con trỏ đến các loại mảng mà bạn có. Điều đó sẽ hiệu quả.

+1

không có điều đó không hoạt động. Hàm f của bạn chiếm gấp đôi **, và không phải là một con trỏ tới một mảng. và việc truyền của bạn lên gấp đôi * là sai. nó chỉ đơn giản là không chính xác để đúc một đôi [4] [2] đến một đôi * và hy vọng rằng để làm việc. vì những lý do tôi đã nói ở trên. xin vui lòng không làm điều này. –

+0

Bạn nói đúng, tuyên ngôn của tôi không khớp với những gì tôi đang cố gắng làm. –

+1

Bởi "công việc", bạn có nghĩa là "thất bại khủng khiếp", phải không? Không bao giờ bỏ qua các giá trị một cách mù quáng. –

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