2011-08-23 36 views
6

Loại struct được sử dụng là người đứng đầu danh sách liên kết:Có thể lấy con trỏ đến cấu trúc 'này', khi sử dụng trình khởi tạo được chỉ định không?

struct lista 
{ 
    struct lista* next; 
    struct lista* prev; 
}; 

Khi tới và prev cả điểm để tái cấu trúc bản thân, sau đó danh sách là rỗng. vĩ mô sau đây có thể được sử dụng để khởi tạo cấu trúc:

#define LISTA_INIT_EMPTY(list) { .next = (list), .prev = (list) } 

theo cách này:

struct lista my_list = LISTA_INIT_EMPTY(&my_list); 

Nhưng, liệu có cách nào để làm điều tương tự bằng cách sau, mà không cần thông số vĩ mô ?:

struct lista my_list = LISTA_INIT_EMPTY; 

tôi đã thử các sau đây, nhưng nó gây ra một lỗi biên dịch:

#define LISTA_INIT_EMPTY  { .next = &.next, .prev = &.next } 

Trả lời

6

Vâng, cách duy nhất tôi thấy là khó chịu:

#define LISTA_INIT_EMPTY  { .next = (&my_list), .prev = (&my_list) } 

Không thoải mái ở tất cả vì nó chỉ hoạt động nếu biến của bạn được gọi là my_list. Và không có cách nào tốt đẹp như this không tồn tại trong C.

Tại sao không sử dụng NULL thay vì trỏ đến "này"? Nếu điều này là không thỏa đáng, việc giữ macro tham số có lẽ là tốt nhất.

EDIT: (nhờ comment R dưới đây, tôi cuối cùng đã hiểu sự cần thiết):

Như không có "này" và chỉ nhập tên của biến một lần, tôi khuyên bạn nên sử dụng một macro như vậy:

#define CREATE_EMPTY_LISTA(name) struct lista name = { .next=&name, .prev=&name } 

Và sau đó trong các mã:

CREATE_EMPTY_LISTA(my_list); // creates and initializez my_list at the same time 
+2

Tôi nghĩ OP muốn tất cả các danh sách, bao gồm cả cái trống rỗng ban đầu, là hình tròn. Điều này không hoàn toàn bất hợp lý; thường nó loại bỏ tất cả các trường hợp góc xấu xí trong các hàm xử lý danh sách của bạn. –

+1

'CREATE_EMPTY_LISTA' về cơ bản giống với' LISTA_INIT_EMPTY' được OP đề cập. –

+1

Có, nhưng với một sự khác biệt quan trọng: 'struct lista my_list = LISTA_INIT_EMPTY (& my_list);' buộc bạn phải lặp lại tên của biến, mà không phải là tốt đẹp và khá dễ bị lỗi. 'CREATE_EMPTY_LISTA (my_list);' cho phép bạn không lặp lại nó. – Shlublu

0

Không thực sự! Nếu bạn xác định sản phẩm nào như NULL thay vì "bản thân", sau đó bạn có thể làm điều đó bằng cách:

#define LISTA_INIT_EMPTY {NULL,NULL}

0

Rõ ràng đây là không thể, kể từ khi khối cần phải biết các trường hợp.

Ngoài ra .next = &.next sẽ không hoạt động vì các loại không khớp. (struct lista* to struct lista**)

0

Không, trình khởi tạo của bạn tạo ra struct lista và sau đó gán my_list cho nó. Ý tưởng của bạn về một this không có ý nghĩa trong ngữ cảnh này, nó sẽ không trỏ đến my_list cho đến khi nó được gán.

2

Lưu ý rằng kỹ thuật khởi tạo danh sách của bạn tương tự như những gì được sử dụng trong nguồn hạt nhân Linux cho danh sách được liên kết của chúng (include/linux/list.h).

Đối khởi của một danh sách khi người đứng đầu danh sách được công bố, thay vì cố gắng làm điều gì đó như:

// won't work: 
struct lista my_list = /* something or other */; 

Linux sử dụng một macro mà thực hiện cả delcaration và khởi tạo (vì vậy người dùng vẫn phải chỉ sử dụng tên một lần). Đối với struct lista của bạn nó có thể trông giống như:

#define LISTA_HEAD struct lista name = LISTA_INIT_EMPTY(name) 

// this is all the user needs to do to both declare and initialize a list: 
LISTA_HEAD(my_list); 

Hãy xem include/linux/list.h cho tất cả các chi tiết. Ngoài ra còn có giải thích thoải mái về cách thức hoạt động danh sách làm việc (không phải tất cả của nó là trực quan):

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