2011-12-14 51 views
16

xin vui lòng xem xét các đoạn mã sau:typedef con trỏ const weirdness

typedef struct Person* PersonRef; 
struct Person { 
    int age; 
}; 

const PersonRef person = NULL; 

void changePerson(PersonRef newPerson) { 
    person = newPerson; 
} 

Đối với một số lý do, trình biên dịch được comlaining về read-only giá trị không thể chuyển nhượng. Nhưng từ khóa const không được làm cho con trỏ const. Bất kỳ ý tưởng?

+2

"Nhưng từ khóa const không được tạo thành con trỏ const." Huh? Câu trả lời ngắn: không sử dụng typedefs, chúng chỉ ở đó để gây nhầm lẫn cho bạn. Hãy nhớ chúng cho đến khi bạn cần chúng. – wildplasser

+12

@wildplasser: "Không sử dụng typedef" không phải là lời khuyên tốt. Có lẽ "Đừng giấu con trỏ đằng sau typedefs" là thích hợp hơn ... –

+1

Tôi cầu xin sự khác biệt. Nó * là * một lời khuyên tốt. Ẩn cấu trúc đằng sau một typedef chỉ là khó hiểu như ẩn con trỏ. Nó chỉ phục vụ để gây ô nhiễm không gian tên tinh thần của bạn. Ngay cả khi không có cú pháp tô sáng tôi đọc "struct person * p" dễ dàng hơn và nhanh hơn sau đó "pPerson p". – wildplasser

Trả lời

33

Lưu ý rằng

typedef int* intptr; 
const intptr x; 

là không giống nhau như:

const int* x; 

intptr là con trỏ đến int. const intptr là con trỏ liên tục đến int, không trỏ đến hằng số int.

vì vậy, sau một con trỏ typedef, tôi không thể biến nó thành nội dung nữa?

Có một số cách xấu xí, chẳng hạn như gcc của typeof macro:

typedef int* intptr; 
intptr dummy; 
const typeof(*dummy) *x; 

nhưng, như bạn thấy, đó là vô nghĩa nếu bạn biết loại đằng sau intptr.

+0

vì vậy, sau một con trỏ typedef, tôi không thể biến nó thành nội dung nữa? – Johannes

5
const PersonRef person = NULL; 

struct Person*const person= NULL; 

vì vậy bạn đang consting con trỏ và không phải là đối tượng.

+0

vì vậy, sau khi một con trỏ typedef, tôi không thể làm cho nó const đến nội dung nữa? – Johannes

+1

vâng, chính xác, một trong những lý do tại sao 'typedef' của con trỏ thường là một ý tưởng tồi. –

0

bạn đang nhận được và lỗi

error: assignment of read-only variable ‘person’ 

trên tuyên bố

person = newPerson; 

vì bạn đã tuyên bố người như const vì thế giá trị của nó chỉ read only .... giá trị const không thể thay đổi

nếu bạn định thay đổi điều đó, thì tại sao bạn đang dùng nó?

xóa từ khóa const mã của bạn sẽ hoạt động tốt

+0

vâng, chắc chắn, tôi chỉ tự hỏi tại sao con trỏ ist const và không phải là nội dung mà nó trỏ đến.đó là những gì tôi mong đợi ... – Johannes

1

Không bao giờ ẩn con trỏ phía sau typedefs, nó thực sự là thực sự tồi tệ và sẽ chỉ tạo lỗi.

Một lỗi khét tiếng như vậy là một kiểu con trỏ typedef: ed được khai báo là const sẽ được coi là "con trỏ liên tục đến dữ liệu không liên tục", thay vì "con trỏ không liên tục đến dữ liệu không đổi" những gì người ta trông đợi một cách trực giác. Đây là những gì xảy ra trong chương trình của bạn.


Giải pháp:

typedef struct 
{ 
    int age; 
} Person; 

const Person* person = NULL; // non-constant pointer to constant Person 
3

Trong khi vấn đề đã được giải quyết bằng các câu trả lời ở trên, tôi làm lỡ lý do tại sao ...

Vì vậy, có lẽ như một quy luật của:

  1. Các const luôn đề cập đến nó là người tiền nhiệm của thẻ.
  2. Trong trường hợp không có, thay vào đó, "sắp xếp" đó là mã thông báo kế thừa.

Quy tắc này thực sự có thể giúp bạn để khai báo con trỏ tới con trỏ const hoặc thứ gì đó gọn gàng như nhau.

Dù sao, với điều này trong tâm trí, nó sẽ nhận được rõ ràng lý do tại sao

struct Person *const person = NULL; 

khai báo một con trỏ const đến một cấu trúc có thể thay đổi.

Hãy nghĩ về điều đó, typedef "nhóm" của bạn struct Person bằng mã thông báo con trỏ *. Vì vậy, để viết

const PersonRef person = NULL; 

trình biên dịch của bạn thấy một cái gì đó như thế này (pseudo-code):

const [struct Person *]person = NULL; 

Như không có gì để const 's trái là, nó deklares token để nó ở ngay struct Person * liên tục.

Vâng tôi nghĩ, đây là lý do tại sao tôi không thích ẩn con trỏ bởi typedefs, trong khi tôi làm như typedefs như vậy. Điều gì về cách viết

typedef struct Person { ... } Person; 
const Person *person; /*< const person */ 
Person *const pointer; /*< const pointer to mutable person */ 

và nó phải khá rõ ràng với trình biên dịch và con người, những gì bạn đang làm.

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