2012-02-07 37 views
5

Vài ngày trở lại tôi đã có một cuộc phỏng vấn nhưng, tôi vẫn đang tìm kiếm câu trả lời. Tôi muốn hiểu tầm quan trọng của việc sử dụng từ khóa dễ bay hơi.Sự khác biệt giữa biến động & extern là gì?

Tìm mã bên dưới: Hai trường hợp khác nhau.

//project1 
//File1.c 

int abc;//Global variable 
/*And this variable is getting used in some other files too.*/ 
if(abc == 3) //Say 
{ 
    printf("abc == 3"); 
} 
else 
{ 
    printf("abc != 3"); 
} 
/*So if or else part will not be optimized 
because "abc" can not be predicted, 
the value can chage at any point of time */ 




//Project2 
//file1.c 

volatile int abc;//Global variable with volatile keyword 

/*And this variable is getting used in some other files too.*/ 

if(abc == 3) //Say 
{ 
    printf("abc == 3"); 
} 
else 
{ 
    printf("abc != 3"); 
} 
/*So if or else part will not be optimized 
because "abc" can not be predicted as it is declared as volatile, 
the value can chage at any point of time */ 

Tại sao chúng ta nên sử dụng từ khóa dễ bay hơi thay thế?

+0

có thể trùng lặp của [Sự khác biệt giữa biến biến động tĩnh và tĩnh tĩnh là gì?] (Http: // stackoverflow.com/questions/346306/cái gì-là-sự khác biệt-giữa-một-tĩnh-toàn cầu-và-tĩnh-biến động-biến) – NPE

+5

dễ bay hơi và extern là hoàn toàn không liên quan. –

+0

@MarkByers: Bạn nói đúng, nhưng theo câu hỏi của người phỏng vấn, cả hai điều trên đều tương tự nhau. Vậy tại sao dễ bay hơi? –

Trả lời

5

Vì Tony Delroy giải thích trong nhận xét của mình, externvolatile hoàn toàn khác nhau.


dễ bay hơi từ khóa bảo vệ biến của bạn khỏi bị tối ưu hóa mạnh mẽ. Một biến được tối ưu hóa có thể ẩn với các chủ đề khác và không bao giờ đạt tới bộ nhớ chính. Đôi khi, trình biên dịch có thể even squeeze entirely một biến nếu nó không cần thiết. Trình biên dịch dựa trên dự đoán của nó với mã nguồn của bạn làm đầu vào duy nhất của nó. Đôi khi, có một số sự kiện bên ngoài có thể thay đổi giá trị biến của bạn. Nó có thể là một thiết bị phần cứng hoặc một quá trình khác, ví dụ.

=> Cụ thể, trình biên dịch vô hiệu hóa một số tối ưu hóa cho biến này, do đó, nó có thể hoạt động như bạn muốn.


Extern không phải về bộ nhớ cache so với bộ nhớ. Extern chỉ là về việc truy cập một biến nằm trong một tệp đối tượng khác. Xem this short example loại mã lắp ráp được tạo cho một truy cập extern. Những biến số extern này được tối ưu hóa trong tệp đối tượng của riêng chúng nhiều nhất có thể. Không có câu hỏi về việc bảo vệ nó hay không.

=> Cụ thể, biên dịch cho thấy một tài liệu tham khảo bên ngoài cần phải được giải quyết vào thời điểm liên kết

+0

Con trỏ khung và extern không liên quan. Khung con trỏ được sử dụng cho các biến stack (lớp lưu trữ tự động), extern là toàn cầu (lớp lưu trữ tĩnh) và không cần bất kỳ con trỏ khung nào. – Suma

+0

damn, tôi đã tái cheched và bạn nói đúng. Tôi sẽ loại bỏ phần này của câu trả lời của tôi – Coren

+1

Giải thích về extern là khó hiểu. –

4

dễ bay hơi trong việc kê khai hoặc nguyên mẫu nói luôn nạp/lưu trữ giá trị từ/vào bộ nhớ bất kể địa phương, tĩnh hoặc extern vlaue này (nhưng trong trường hợp địa phương nó không phải là luôn luôn có ý nghĩa).

Cũng sử dụng dễ bay hơi từ khóa trong nguồn thông thường là không bình thường. Nó chỉ hữu dụng cho phần cứng mà phần cứng bản đồ đăng ký vào bộ nhớ (như trong kiến ​​trúc ARM), trong các trường hợp đặc biệt của sự phát triển kernel/driver.

Nếu bạn sử dụng dễ bay hơi trong GUI hoặc mã thương mại điện tử, có thể bạn đã sai ...

+1

Câu hỏi được gắn thẻ là được nhúng, nơi dễ bay hơi rất điển hình. Biến động trong các biến tự động (cục bộ) có ý nghĩa, ví dụ như các bộ đếm vòng lặp cho việc thực hiện trễ: 'for (biến động không dấu int i = delay; i> 0; --i) {}'. Vì vòng lặp không có gì hợp lý, một trình tối ưu hóa có thể loại bỏ nó nếu nó không phải là 'biến động'. – Gauthier

+1

Cũng hữu ích khi tạo ví dụ: một biến gỡ lỗi, nơi bạn có thể ghi vào một biến mà chương trình không bao giờ đọc và có ý định đọc nội dung sau trong trình gỡ lỗi. 'static volatile uint8_t debug_buffer [64];' Vì trình biên dịch thấy rằng các giá trị được lưu không bao giờ được tái sử dụng, nó cũng có thể loại bỏ việc viết. 'volatile' ngăn chặn điều đó. – Gauthier

+0

@Gauthier Cảm ơn lời khuyên! Tôi nhớ rằng một số nền tảng nhúng cho phép dừng thực thi trên bộ nhớ truy cập vào địa chỉ nhất định để bạn có thể dễ dàng theo dõi bất kỳ thay đổi giá trị biến mà không mất hiệu suất thực hiện bằng cách đánh dấu nó như volataile. – gavenkoa

2

volatile thường có nghĩa là một hoặc nhiều điều sau đây:

  1. Biến có thể bị thay đổi bởi một thread OS
  2. Dòng chảy bình thường thực hiện trong chương trình có thể bị gián đoạn bởi một tín hiệu và xử lý tín hiệu có thể thay đổi biến số
  3. Luồng thực thi bình thường đang chạy vòng lặp, biến được đọc trong vòng lặp và biến được thay đổi bằng điểm 1 hoặc 2

volatile có nghĩa là trong suốt vòng đời của chương trình có hai (hoặc nhiều hơn) đọc R1 và R2 của biến, và một số sự kiện khác xảy ra giữa R1 và R2 sẽ thay đổi biến bên ngoài luồng thực thi bình thường.


extern có nghĩa là biến đã được xác định ở đâu đó và chương trình đang sử dụng lại định nghĩa đó.

-1

Về bản chất, dễ bay hơi được sử dụng để cho biết rằng giá trị của biến sẽ được sửa đổi bởi các luồng khác nhau.

Khai báo một biến Java dễ bay hơi có nghĩa là:

The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory"; 
Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself. 

extern về cơ bản có nghĩa là tất cả các module có thể sử dụng các biến được định nghĩa.

1

Tôi không hoàn toàn đồng ý với các câu trả lời trước đây vì vậy đây là hai xu của tôi.

Bằng cách khai báo biến biến động bạn đang nói với trình biên dịch rằng giá trị của nó có thể thay đổi bất kỳ lúc nào và không thể đưa ra bất kỳ giả định nào về giá trị của biến, thậm chí trong hai lệnh liên tiếp (assembly). Kết quả là bất kỳ việc sử dụng biến nào cũng phải được thực hiện bằng cách truy cập vào biến thực tế và không phải là giá trị được lưu trữ.

Trong mã bạn đã cung cấp, không có sự khác biệt về hành vi giữa abc là toàn cầu, extern hoặc dễ bay hơi vì if()/else chỉ đánh giá biến một lần. Có sự khác biệt tuy nhiên nếu bạn thay đổi khác bởi một thứ hai nếu, như trong:

if(abc == 3) 
{ 
    printf("abc == 3"); 
} 
if (abc != 3) 
{ 
    printf("abc != 3"); 
} 

Nếu abc là không tuyên bố không ổn định, trình biên dịch có thể tối ưu hóa thứ hai nếu và thay thế nó bằng một tuyên bố khác, hậu quả abc sẽ chỉ được đọc và đánh giá một lần, có nghĩa là dấu xor đầu tiên thứ hai sẽ được thực hiện (nhưng không phải cả hai và cũng không phải là không có).

Nếu abc IS tuyên bố dễ bay hơi (không quan trọng nếu cục bộ, toàn cầu hoặc bên ngoài), trình biên dịch buộc phải đánh giá abc hai lần vì giá trị của nó có thể thay đổi ở giữa. Điều này có nghĩa là bất kỳ bản in nào, hoặc cả hai, hoặc không có, có thể được thực hiện.

Extern là một câu chuyện khác hoàn toàn. Tất cả những gì nó làm là cho trình biên dịch biết rằng biến đã được định nghĩa trong một tệp khác (có địa chỉ sẽ được cung cấp tại thời gian liên kết). Nếu trình biên dịch có thể dự đoán rằng giá trị của abc sẽ không thay đổi giữa hai câu lệnh if (nó không quan trọng như thế nào trình biên dịch có thể), thì nó vẫn có thể tối ưu hóa thứ hai nếu thành một cái khác và giảm hai abc đánh giá một.

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