2012-03-16 51 views

Trả lời

12

constvolatile được gọi là "kiểu vòng loại". Cú pháp của họ là một trong những điều khó hiểu nhất trong C.

Trước hết, chúng tôi có trường hợp với một biến thông thường. Bạn thường viết loại định danh trước tên biến: const int x;, nhưng cũng tốt để viết nó sau tên biến: int const x;. Ý nghĩa là như nhau, cú pháp thứ hai là chỉ có để gây nhầm lẫn.

Khi khai báo con trỏ, bạn quan tâm đến hai loại: loại con trỏ chính nó và loại được trỏ vào. Với các con trỏ thông thường, điều này là tầm thường: int* x có nghĩa là kiểu con trỏ là con trỏ tới int và kiểu chỉ trỏ là int.

Nếu điểm được chỉ định là const int, con trỏ được khai báo là const int* x. Con trỏ có kiểu là pointer-to-const-int và kiểu được trỏ tới là const int. Nếu bạn muốn gây nhầm lẫn cho mọi người, bạn cũng có thể viết int const* x, tương đương.

Hãy để chúng tôi nói rằng chúng tôi muốn bản thân con trỏ cũng không đổi. Vì lý do nào đó, chúng tôi muốn chặn lập trình viên thay đổi địa chỉ được chỉ ra. Ví dụ, có lẽ con trỏ sẽ được lưu trữ trong bộ nhớ chỉ đọc của một hệ thống nhúng. Một con trỏ liên tục đến dữ liệu, được khai báo là int*const x; với từ khóa const sau dấu *. Loại được chỉ định trong trường hợp này là intkhôngconst int.(Tôi cố gắng viết các const cùng với các *, không có không gian ở giữa, để cho nhấn mạnh rằng con trỏ là không đổi)

Nếu chúng ta muốn chỉ-to-type là không đổi là tốt, chúng tôi sẽ phải kết hợp hai khai báo trên: const int*const x; có nghĩa là một con trỏ liên tục trỏ vào một hằng số int.

const int x;   // x is a constant data variable 
int const x;   // x is a constant data variable 

const int* x;   // x is a non-constant pointer to constant data 
int const* x;   // x is a non-constant pointer to constant data 

int*const x;   // x is a constant pointer to non-constant data 

const int*const x; // x is a constant pointer to constant data 

Trong các ví dụ trên tôi đã sử dụng loại vòng loại const. Nhưng volatile cũng là một loại vòng loại, và nó hoạt động theo cách chính xác như nhau! Có thể khai báo các con trỏ không bay hơi đến các dữ liệu dễ bay hơi, vv.

Và cuối cùng, có thể kết hợp các loại vòng loại khác nhau. Ví dụ: volatile const int* là một con trỏ không ổn định, không bay hơi đến dữ liệu const dễ bay hơi. Một lần nữa, chúng tôi có tùy chọn tuyệt vời để trộn thứ tự của những thứ này để gây nhầm lẫn, vì vậy chúng tôi cũng có thể viết volatile int const * hoặc int volatile const * v.v ... và tất cả đều giống nhau.

+0

+1, giải thích tốt về loại vòng loại, nhưng OP hỏi tại sao nó được sử dụng trong mã số – jeb

+0

Cảm ơn bạn. Một câu hỏi nhanh. Là 'int * x' tương đương với' int * int x'? – Randomblue

+0

'volatile const int * ptr *' -> trỏ tới dữ liệu đã được cấp quyền Read chỉ bởi mã, nhưng có thể được sửa đổi bởi các sự kiện bên ngoài (ngắt vv) –

6

Tôi hiểu số volatile unsigned int * bit, nhưng tại sao là const ở đó?

Điều đó có nghĩa là con trỏ là hằng số, có nghĩa là con trỏ không thể (thay vì không) trỏ đến bất kỳ địa chỉ nào khác.

Lưu ý những điều sau đây, xây dựng:

volatile unsigned int * const UART0DR = 

Pointer là hằng số ở đây.


volatile unsigned int const * UART0DR = 

Địa chỉ nhọn là hằng số ở đây.


volatile unsigned int const * const UART0DR = 

Địa chỉ nhọn cũng như con trỏ là hằng số trong trường hợp này.

+0

Cảm ơn. Vì vậy, là 'const' cho một số loại tối ưu hóa trình biên dịch? – Randomblue

+0

@Randomblue: Nó là một vòng loại cho trình biên dịch biết rằng thực thể cụ thể này là hằng số và sẽ không thay đổi. Điều này giúp trình biên dịch chỉ ra các lỗi trong cùng một trường hợp trong khi cũng * có thể * cho phép trình biên dịch áp dụng tối ưu. người dùng mã nguồn của bạn là thông tin quan trọng về biến cụ thể chỉ bằng cách đọc khai báo của nó. –

+1

"Địa chỉ chính là không đổi ở đây". Thay vào đó, _ nội dung_ của địa chỉ được trỏ đến. – Lundin

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