2011-02-10 25 views
5
#include <stdio.h> 
#include <stdlib.h> 
typedef struct { 
    unsigned length; 
} List; 
void init(List *l) { 
    l = (List *) malloc(sizeof(List)); 
    l->length = 3; 
} 
int main(void) { 
    List *list = NULL; 
    init(list); 
    if(list != NULL) { 
     printf("length final %d \n", list->length); 
     return 0; 
    } 
    return 1; 
} 

Đây là phiên bản đơn giản của mã đang gây ra sự cố cho tôi. Tôi đang cố gắng để xây dựng con trỏ *list từ một phương pháp trong đó *list được chuyển thành một tham số.C - Không thể khởi tạo con trỏ được chuyển làm đối số

Tôi biết tôi có thể làm cho void init(List *l) hoạt động bằng cách thay đổi thành void init(List **l) nhưng đây là hướng dẫn về lớp học. Tôi không thể thay đổi các đối số phương thức. Tôi đã dành bốn giờ làm việc về điều này.

Tôi muốn đảm bảo rằng không có cách nào để làm cho void init(List *l) hoạt động trước khi tôi đối đầu với giáo sư của mình.

Cảm ơn trước

Trả lời

4

Bạn đang đi qua một bản sao của con trỏ đến init, được phân bổ bộ nhớ, lưu trữ nó trong bản sao cục bộ của nó, và ngay lập tức bị rò rỉ nó khi init lợi nhuận. Bạn không thể chuyển dữ liệu trở lại chức năng gọi theo cách này. Bạn cần trả về dữ liệu được cấp phát hoặc chuyển một con trỏ tới con trỏ bạn muốn sửa đổi, cả hai đều liên quan đến việc sửa đổi chữ ký hàm.

void init(List **l) { 
    *l = (List *) malloc(sizeof(List)); 
    (*l)->length = 3; 
} 

init(&list); 

đã phân công xác định rằng bạn phải phân bổ các List từ bên trong init? Nếu không, bạn luôn có thể vượt qua một con trỏ đến một đã được phân bổ List đối tượng và thực hiện bất cứ điều gì khởi length = 3 là một nơi-giữ cho:

void init(List *l) { 
    l->length = 3; 
} 

List list; 
init(&list); 
printf("length final %d \n", list.length); 
+1

PO được đề cập cụ thể nếu nó có thể được thực hiện tránh "void init (Danh sách ** l)" –

+0

@Gunner gửi – meagar

+0

Nhiệm vụ chỉ định rằng nó phải là hàm tạo. Tôi sẽ gửi email cho giáo sư của tôi và yêu cầu anh ta thay đổi các yêu cầu. Cảm ơn bạn đã giúp đỡ! –

3

Vấn đề là con trỏ được truyền theo giá trị, vì vậy bạn thay đổi bị hủy. Bạn thực sự cần một con trỏ đến một con trỏ để làm điều này một cách chính xác. Như trong bạn sẽ làm gì:

void init(List** l) { 
    *l = (List*) malloc(sizeof(List)); 
    // ... 
} 

Và khi bạn gọi nó, bạn sẽ sử dụng init(&list) thay vì init(list). Tất nhiên, trong trường hợp này, nó làm cho tinh thần để chỉ cần đi trước và trả kết quả thay vì sử dụng một con trỏ đến một con trỏ:

List* init() { 
    List* result = (List *) malloc(sizeof(List)); 
    result->length = 3; 
    return result; 
} 

Và sau đó, với việc trên, bạn chỉ có thể sử dụng list = init();.

Lưu ý rằng trong C++, bạn có thể sử dụng tham chiếu thay cho con trỏ, nhưng việc trộn tham chiếu và con trỏ thì vô cùng lộn xộn. Ở đây, việc sử dụng kiểu trả về thực sự là điều gọn gàng nhất để làm.

Nếu bạn hoàn toàn phải sử dụng chữ ký hiện có, bạn có thể lén lút và khởi tạo danh sách, sau đó trong hàm init() bạn có thể làm điểm trỏ kế tiếp của danh sách được chuyển vào danh sách bạn thực sự muốn tạo. Sau đó, sau khi init() được gọi, bạn có thể lấy con trỏ tiếp theo và vứt bỏ đối tượng danh sách ban đầu mà bạn đã tạo. Hoặc bạn luôn có thể có yếu tố đầu tiên bởi một số yếu tố giả.

1

bài tập này có lẽ là một cách hay để dạy trong một lớp học bằng giá trị và vượt qua bằng tham chiếu. Nếu bạn muốn duy trì chữ ký của hàm tạo, bạn cần sửa đổi hàm main.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
typedef struct { 
    unsigned length; 
} List; 


void init(List *l) { 
    l->length = 3; 
} 
int main(void) { 
    List list;// x = NULL; 
    memset(&list,0,sizeof(List)); 
    init(&list); 
    printf("length final %d \n", list.length); 
    return 1; 
} 

Hiện tại danh sách này thuộc loại Danh sách và không phải là địa chỉ trong Danh sách. phương thức init() truyền địa chỉ của danh sách và bên trong init bạn có thể thay đổi giá trị của nội dung cấu trúc.

./a.out

dài thức 3

+0

Tôi cho rằng việc ghi nhớ là vi phạm đóng gói. init chịu trách nhiệm initing nội dung của danh sách; nếu một bộ nhớ là cần thiết, nó nên làm điều đó. Vì nó là, nó không phải là cần thiết. –

0

init cần phải được thông qua một con trỏ đến một danh sách hiện có. Tôi nghi ngờ rằng vấn đề thực sự ở đây là với cấu trúc dữ liệu của bạn. Bạn có một cái gì đó gọi là một danh sách, có chứa một chiều dài, nhưng không có danh sách để được nhìn thấy bất cứ nơi nào. Danh sách có lẽ nên chứa một con trỏ đến một mảng có chiều dài đã cho, và init nên malloc mảng đó và thiết lập con trỏ. Có thể bạn sẽ tìm thấy điều này khi bạn yêu cầu giáo sư sửa chữa các yêu cầu của mình mà không bị hỏng - nếu có, có lẽ anh ta đã nghe về nó từ các sinh viên trong quá khứ và sửa chúng ngay bây giờ.

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