2012-03-29 38 views
57

volatile là yêu cầu trình biên dịch không tối ưu hóa tham chiếu, để mọi đọc/ghi không sử dụng giá trị được lưu trữ trong thanh ghi nhưng thực sự truy cập bộ nhớ thực. Tôi có thể hiểu nó rất hữu ích cho một số biến thông thường, nhưng không hiểu làm thế nào volatile ảnh hưởng đến một con trỏ.Tại sao con trỏ trỏ tới điểm dễ bay hơi, như "int dễ bay hơi * p", hữu ích?

volatile int *p = some_addr; 
int a = *p; // CPU always has to load the address, then does a memory access anyway, right? 

Sự khác biệt nếu nó được khai báo là int *p = some_addr?

Trả lời

101

Một con trỏ có dạng

volatile int* p; 

là một con trỏ đến một int rằng trình biên dịch sẽ coi như volatile. Điều này có nghĩa rằng trình biên dịch sẽ giả định rằng có thể cho biến mà p trỏ vào đã thay đổi ngay cả khi không có gì trong mã nguồn để gợi ý rằng điều này có thể xảy ra. Ví dụ, nếu tôi đặt p để trỏ đến một số nguyên thông thường, sau đó mỗi khi tôi đọc hoặc viết *p trình biên dịch nhận thức được rằng giá trị có thể đã thay đổi bất ngờ.

Có một trường hợp sử dụng khác cho số volatile int*: Nếu bạn khai báo intvolatile, thì bạn không nên chỉ định trường hợp này với số int* thông thường. Ví dụ, đây là một ý tưởng tồi:

volatile int myVolatileInt; 
int* ptr = &myVolatileInt; // Bad idea! 

Lý do cho điều này là trình biên dịch C không còn nhớ rằng biến chỉ vào bởi ptrvolatile, vì vậy nó có thể bộ nhớ cache giá trị của *p trong một thanh ghi không đúng cách . Trong thực tế, trong C++, mã trên là một lỗi. Thay vào đó, bạn nên viết

volatile int myVolatileInt; 
volatile int* ptr = &myVolatileInt; // Much better! 

Bây giờ, trình biên dịch nhớ rằng ptr điểm tại một volatile int, vì vậy nó sẽ không (hay không!) Nên cố gắng tối ưu hóa truy cập thông qua *ptr.

Một chi tiết cuối cùng - con trỏ bạn đã thảo luận là con trỏ đến volatile int. Bạn cũng có thể làm điều này:

int* volatile ptr; 

này nói rằng con trỏ tựvolatile, có nghĩa là trình biên dịch không nên cố gắng để cache con trỏ trong bộ nhớ hoặc cố gắng tối ưu hóa giá trị con trỏ vì con trỏ bản thân có thể được bố trí bởi cái gì khác (phần cứng, một chủ đề, vv) bạn có thể kết hợp này lại với nhau nếu bạn muốn để có được con thú này:

volatile int* volatile ptr; 

này nói rằng cả hai con trỏ và pointee có thể bị thay đổi bất ngờ . Trình biên dịch không thể tối ưu hóa con trỏ chính nó, và nó không thể tối ưu hóa những gì đang được chỉ ra.

Hy vọng điều này sẽ hữu ích!

+0

Tôi nghĩ rằng bạn có nghĩa là "bạn KHÔNG nên chỉ vào nó với một int thường xuyên *" – markgz

+0

@ markgz- Rất tiếc! Vâng đúng rồi. Đã sửa. – templatetypedef

+0

Tôi nghĩ rằng đó là một lỗi trong C là tốt, nhưng trình biên dịch C ít dễ bị phàn nàn về loại không phù hợp. –

6

Mã này volatile int *p = some_addr khai báo con trỏ đến volatile int. Con trỏ chính nó không phải là volatile.

Trong trường hợp không chắc rằng bạn cần các con trỏ đến biến động cũng như int, bạn sẽ cần phải sử dụng:

volatile int * volatile p; 

Tôi không thể nghĩ ra một tình huống mà bạn sẽ cần phải sử dụng .

+2

Ví dụ: Tôi 'sử dụng' uint8_t dễ bay hơi * biến động pData 'trong mã ISR để sửa đổi con trỏ và dữ liệu mà nó trỏ tới. Con trỏ được thiết lập bởi mã chính, và cả hai con trỏ và dữ liệu được đọc sau. – Christoph

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