2013-09-05 63 views
11

Trong khi điều này biên dịch:Gán con trỏ để trỏ có hoặc không có vòng loại

char* p2c; 
const char* p2cc = p2c; //fine 

vì LHS nhọn loại có tất cả các vòng loại của RHS loại nhọn, điều này không:

char** p2p2c; 
const char** p2p2cc = p2p2c; //fail 

nhưng điều này không:

const char * const * p2cp2cc = p2p2c; //fine 

Tại sao điều này lại xảy ra?

+1

Ví dụ cuối cùng sẽ chỉ biên dịch trong C++, nhưng không phải trong C. – AnT

+0

@AndreyT tại sao như vậy? – emesx

+0

Đó chỉ là cách thức của nó trong C và C++. Đây là hai ngôn ngữ khác nhau với các quy tắc const-correctness khác nhau. Trong C++ 'T **' có thể chuyển đổi thành 'const T * const *'. Trong C 'T **' có thể chuyển đổi thành 'T * const *', nhưng không chuyển thành 'T * const *'. http://stackoverflow.com/a/5249001/187690 – AnT

Trả lời

7

này không hoạt động:

char** p2p2c; 
const char** p2p2cc = p2p2c; //fail 

Nếu được cho phép, bạn sẽ được phép phá vỡ const-đúng đắn:

const int k = 10; 
int *p; 
int **pp = &p; 
int const **kpp = pp;  // Should this be allowed, if so: 
*kpp = &k;    // fine, kpp promises not to change it 
          // yet this does p = &k; 
          // p made no such promise! this is a hidden const_cast! 
*p = 5; 

Nếu việc chuyển nhượng được cho phép, bạn sẽ cho phép thiết lập một con trỏ không const (trung gian) để tham chiếu đến một giá trị không đổi, có thể gây ra hành vi không xác định trong một không rõ ràng để xem cách. Bằng cách không cho phép hoạt động đó, hệ thống kiểu an toàn hơn.

nhưng điều này không:

const char * const * p2cp2cc = p2p2c; //fine 

này là tốt, kể từ khi con trỏ trung gian là cố định, nó là không thể để thiết lập lại con trỏ trung gian để đề cập đến một đối tượng const và phá vỡ const-đúng đắn

+0

Tại sao người ta có thể chuyển đổi một cách an toàn 'char **' thành 'char const * const *'? – emesx

+0

@elmes: vì con trỏ trung gian cũng là 'const' có nghĩa là bạn không thể đặt lại nó thành đối tượng * sai *. –

+0

Dường như khá hợp lý, cảm ơn. – emesx

-1

cdecl thực sự giúp trong các trường hợp như thế này.

const char** p2p2cc = declare p2p2cc as pointer to pointer to const char 

const char * const * p2cp2cc = declare p2cp2cc as pointer to const pointer to const char 

Như bạn có thể thấy, phiên bản thứ hai có nội VÀ con trỏ const bên ngoài, có nghĩa là nó không thể thay đổi một trong hai. Phiên bản đầu tiên có const con trỏ INNER và non-const bên ngoài do đó phá vỡ constnes.

Mặt khác, hoạt động này:

char** const p = p2p2c;