2013-04-15 38 views
9

(Trước khi tôi bắt đầu: Tôi biết có existingquestions về chủ đề này, nhưng không ai tôi đã tìm thấy câu trả lời tại sao đây là một vấn đề tôi làm điều đó thường xuyên và muốn biết nếu tôi đang tạo ra vấn đề tiềm ẩn..)Tại sao loại bỏ vòng loại dễ bay hơi trong một hàm gọi cảnh báo?

Tôi rất tò mò tại sao loại bỏ vòng loại dễ bay hơi trong một cuộc gọi hàm có giá trị cảnh báo trình biên dịch.

Tình hình là như sau:

volatile uint8_t thingy; 
void awesome_function(uint8_t *arg); 

awesome_function(&thingy); << warning 

Bây giờ, sự hiểu biết của tôi là những volatile vòng loại đánh dấu một biến là một trong đó có thể thay đổi theo những cách ngoài tầm kiểm soát của trình biên dịch. Một số tối ưu hóa (quan trọng nhất, theo kinh nghiệm của tôi, việc loại bỏ biến 'không sử dụng') bị vô hiệu hóa.

Tuy nhiên, nếu tôi đánh dấu biến là volatile, tôi quan tâm đến việc ngăn tối ưu hóa trong phạm vi này. Nếu tôi chuyển biến đó thành một hàm, tôi thường hạnh phúc cho việc tối ưu hóa tiêu chuẩn để áp dụng trong hàm đó. *

Đây là trường hợp ngay cả khi trình biên dịch muốn xóa biến khỏi hàm (tối ưu hóa tôi bình thường cố gắng tránh), ngay cả khi nó làm như vậy, nó không ảnh hưởng đến việc tôi sử dụng nó trong phạm vi này; chức năng (kết quả của chính) là điểm thứ tự (và lvalue) mà tôi quan tâm.

Vì vậy, tại sao loại bỏ vòng loại đối với hàm gọi cảnh báo, vì nó sẽ không cho phép sắp xếp lại trong hiện tại phạm vi? Đây có phải là do khả năng sắp xếp lại trong phạm vi chức năng được gọi, không được phép cho biến số volatile? Nếu vậy, tại sao đây là một vấn đề wrt phạm vi hiện tại?

(* điều này là bình thường vì các cuộc gọi như vậy được sử dụng để bắt đầu các hoạt động không đồng bộ, điều này cuối cùng sẽ hoạt động trên con trỏ được chuyển đến hàm đó. Bộ định tính volatile có sẵn để cảnh báo trình biên dịch rằng biến cục bộ sẽ thay đổi không đồng bộ.)

Trả lời

16

Cảnh báo ở đây là vì trình biên dịch giả định rằng khi bạn trỏ đến đối tượng con trỏ volatile, bạn thành thật tin rằng giá trị điểm có thể thay đổi từ một nguồn bên ngoài. Khi bạn chuyển con trỏ này vào một hàm yêu cầu một con trỏ tới một đối tượng không phải là volatile, trình biên dịch cảnh báo bạn rằng cuộc gọi hàm có thể được tối ưu hóa theo cách không chính xác cho thực tế là đối tượng có thể thay đổi.

Thực tế là bạn biết chắc chắn rằng nó không quan trọng để thực hiện điều này có nghĩa là bạn có thể muốn đặt trong một diễn viên rõ ràng mà loại bỏ volatile, như thế này một:

awesome_function((uint8_t*) &thingy); 

này cho rõ ràng trình biên dịch " Tôi biết rằng tôi đang xóa volatile tại đây, vì vậy đừng cảnh báo tôi về điều đó. " Xét cho cùng, toàn bộ điểm cảnh báo là bạn có thể không nhận thấy điều này.

Tương tự tốt sẽ là suy nghĩ về const. Nếu bạn có một con trỏ đến một đối tượng const, bạn hứa sẽ không sửa đổi đối tượng đó thông qua con trỏ.Nếu bạn cố gắng truyền con trỏ này vào một hàm lấy con trỏ đến đối tượng không phải const, bạn sẽ nhận được cảnh báo vì trình biên dịch nhận thấy rằng bạn có thể vô tình kết thúc thay đổi giá trị thông qua hàm. Đặt trong một diễn viên rõ ràng sẽ là một cách để nói với trình biên dịch "có, tôi biết con trỏ này không nên được sử dụng để sửa đổi mọi thứ, nhưng tôi hứa tôi biết những gì tôi đang làm."

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

+0

Tôi chỉ muốn làm rõ: bạn nói rằng 'cuộc gọi chức năng có thể được tối ưu hóa' - bạn có nghĩa là nội dung của hàm hoặc cuộc gọi không? Tôi đã nghĩ rằng sau này sẽ không được tối ưu hóa. Một diễn viên rõ ràng là những gì tôi sử dụng tại thời điểm này (các cuộc gọi có xu hướng để bắt đầu hoạt động chia giai đoạn, và tôi biết biến sẽ không được xúc động ít nhất cho đến sau khi cuộc gọi trả về). – sapi

+0

@ sapi- Tôi có nghĩa là "mã bên trong hàm có thể được tối ưu hóa theo giả định rằng đối tượng được trỏ tới sẽ không bị thay đổi bởi một nguồn bên ngoài." Điều đó có ý nghĩa? – templatetypedef

+0

Trên các nền tảng mà các thanh ghi I/O có một không gian địa chỉ riêng, bỏ đi "dễ bay hơi" đôi khi có thể dẫn đến trình biên dịch truy cập vào vị trí tùy ý trong bộ nhớ khi nó truy cập vào thanh ghi I/O. Đáng kể hơn, tôi sẽ không tin tưởng các tác giả của các trình biên dịch "hiện đại" để tránh lạm dụng các quyền tự do được Tiêu chuẩn cấp để hành xử theo cách tùy ý mà không quan tâm đến việc có bất kỳ thực thể bên ngoài nào làm phiền lưu trữ trong câu hỏi hay không. – supercat

0

Lý do cho volatile không được để ngăn việc tối ưu hóa. Đó là một trong những điều có thể được thực hiện thành biến dễ bay hơi, nhưng lý do là chỉ báo cho trình biên dịch rằng biến có thể thay đổi bên ngoài sự kiểm soát của máy ảo C "". nhiều giả định về nó.

Để kết thúc, đó là thuộc tính của biến thay vì phạm vi của biến số đã nói.

Nếu biến là dễ bay hơi, việc chuyển con trỏ đến biến đó không kỳ diệu làm cho nó không bay hơi, nó chỉ cung cấp cho bạn địa chỉ biến biến động. Đó là như nó phải được.

Nếu bạn chỉ muốn chọn tối ưu hóa dựa trên phạm vi của một biến, volatile không phải là công cụ cho công việc. Bạn sẽ phải tìm một số cách khác (có khả năng không chuẩn), chẳng hạn như vô hiệu hóa cảnh báo cụ thể đó trong khi truyền với #pragma warning - điều này tất nhiên sẽ phụ thuộc vào môi trường của bạn.

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