2012-11-01 37 views
9

Tôi có cấu trúc chứa một số con trỏ. Tôi muốn giá trị của chúng không thể sửa đổi được. Nhưng chỉ đơn giản là viết const infront không làm cho các thành viên structs unmutableconst tính chính xác cho cấu trúc với con trỏ

typedef struct{ 
    int *x; 
    int *y; 
}point; 

void get(const point *p,int x, int y){ 
    p->x[0]=x;//<- this should not be allowed 
    p->y[0]=y;//<- this should not be allowed 
} 

Ai đó có thể chỉ cho tôi đi đúng hướng.

EDIT:

Vì vậy, có vẻ như không có cách nào đơn giản của việc sử dụng các chức năng nguyên mẫu để nói rằng tất cả mọi thứ thuộc về struct nên unmodifiable

+4

Bạn muốn gì không thể sửa đổi? Các chỉ để 'int'? Sau đó 'const int * x;' có nghĩa là bạn không thể sửa đổi giá trị được trỏ tới thông qua con trỏ đó. Các con trỏ? Sau đó 'int * const x;' cấm thay đổi các con trỏ. –

+0

Nếu int * x của tôi, là một mảng, thì tôi muốn các giá trị trong mảng này không thể sửa đổi được. – monkeyking

+0

Sau đó, bạn cần 'const int * x;' trong định nghĩa struct. Lưu ý rằng các giá trị trong mảng vẫn có thể được sửa đổi thông qua các con trỏ khác (có thể gọi hành vi không xác định, nếu 'x' trỏ đến một phần tử' const int arr [3] = {15, 7, 3}; 'hoặc như vậy) . –

Trả lời

2

Để giải thích những gì bạn cần phải thiết lập, khi bạn viết

point str; 

point *p=&str; 

Đây p là một con trỏ đến str đó là loại điểm

Khi bạn khai báo nó như là const, nó có nghĩa là p là một con trỏ không đổi. Điều này không hạn chế các con trỏ mà cấu trúc có thể chứa.

Nếu bạn muốn const ness để áp dụng bên trong cấu trúc, bạn phải xác định các con trỏ bên trong cấu trúc cũng như const

typedef struct{ 
    const int * x; 
    const int * y; 
}point; 

lần nữa để đẩy nhà quan điểm của tôi tuyên bố các thông số như

void get(point * const p,int x, int y) 
    //Constant Pointer (*to prevent p from pointing to anything else*) 

    // AND 

    //Make the pointers inside point structure constant 
    //(*to prevent the int pointers x & y from pointing to anything else*) 

Nếu cấu trúc mà nó trỏ tới cũng const sử dụng

 void get(const point * const p, int x, int y) 
    //Constant Pointer to constant structure 
+0

Nếu các thành viên của tôi trong cấu trúc của tôi được khai báo const, làm cách nào để nhập các giá trị vào nó trong phần đầu của chương trình của tôi. – monkeyking

+0

Bằng cách gõ vào một con trỏ không const. '(int *) (p-> x) = & bất cứ điều gì'. Trong khi nó có thể trông giống như nó sẽ đánh bại mục đích của 'const'ness. Nó có thể rất hữu ích cho các dự án lớn nơi bạn muốn đảm bảo rằng những thay đổi đối với một cấu trúc sẽ chỉ được thực hiện ở một nơi duy nhất được kiểm soát. –

+0

Vì nội dung của con trỏ là hằng số nên nó được khởi tạo trong quá trình khai báo. –

1

Đó là bởi vì bạn thay đổi nội dung bộ nhớ được trỏ đến bởi một con trỏ khác là p.

p điểm trên cấu trúc chứa 2 con trỏ đến int. Bạn không thay đổi bộ nhớ p đang trỏ đến, nhưng một vùng bộ nhớ khác. Vì vậy, trình biên dịch là tốt với điều đó.

 +----------+ 
p -> | x  | -> wherever 
     +----------+ 
     | y  | -> another place in memory 
     +----------+ 

const ness od p không thể kế thừa. Nếu bạn đã viết p->a = array; thì trình biên dịch sẽ bị khiếu nại. const chỉ là hợp đồng nói rằng bạn sẽ không thay đổi bộ nhớ thông qua con trỏ đó.

3

Nếu tôi hiểu câu hỏi của bạn một cách chính xác, bạn muốn nhận được sự truyền bá tự động của constness của toàn bộ đối tượng struct đến các đối tượng được chỉ bởi các thành viên struct đó. I E. nếu đối tượng struct không phải là const, các mảng sẽ có thể sửa đổi được, trong khi nếu đối tượng struct là const, các mảng không thể sửa đổi được.

Nếu có, thì thật không may, nó không thể thực hiện được bằng ngôn ngữ C.

Trong C++ nó có thể được thực hiện bằng cách buộc người dùng sử dụng chức năng thành viên accessor để truy cập các thành viên dữ liệu (thay vì truy cập trực tiếp vào thành viên dữ liệu). Nhưng trong C nó chỉ đơn giản là không thể được thực hiện.

9

Bạn có thể làm điều đó mà không typecasting bằng cách định nghĩa một loại điểm const và một loại điểm có thể thay đổi, sau đó sử dụng một liên minh bạch:

typedef struct{ 
    const int * x; 
    const int * y; 
} const_point; 

typedef struct{ 
    int * x; 
    int * y; 
} mutable_point; 

typedef union __attribute__((__transparent_union__)) { 
    const_point cpoint; 
    mutable_point point; 
} point; 

Sau đó, bạn khai báo các thông số chức năng của bạn bằng cách sử dụng các điểm hoặc loại const_point (không bao giờ loại mutable_point).

đối tượng loại điểm sẽ minh bạch truyền sang loại const_point, nhưng không được đảo ngược. Điều này cho phép bạn có mức độ an toàn cao hơn.

Xem ở đây cho một ví dụ trong gcc: http://toves.freeshell.org/xueg/

Lưu ý rằng liên minh bạch không được hỗ trợ trong phiên bản cuối cùng của C++ Tôi đã kiểm tra (không chắc chắn về các tiêu chuẩn mới nhất C++), do đó bạn có thể mong đợi các vấn đề di.

Nó cũng có thể làm cho mã khó đọc hơn và duy trì, đặc biệt nếu bạn có cấu trúc phức tạp hơn. ví dụ: bạn có thể có loại điểm trong đó x hoặc y là const hoặc bạn có thể cần phải nhúng cấu trúc điểm của mình vào một cấu trúc khác, ví dụ: hình chữ nhật, mà bạn có thể phải xác định nhiều cấu trúc cho nhiều loại tùy thuộc vào độ chói của chúng.

Tất cả trong tất cả, tôi không chắc chắn nó luôn có giá trị thêm rắc rối.

+0

Nó có thể là giá trị rắc rối nếu bạn muốn sử dụng tài liệu tham khảo để bạn có thể nhanh chóng nó với rvalues ​​(kể từ khi bạn có thể sử dụng rvalues ​​với tham chiếu liên tục).Đó có lẽ là trường hợp duy nhất có vẻ khá hữu ích đối với tôi. – meneldal

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