16

Phần §3.9.1/6 từ ++ Chuẩn C nói,Fun với các biến chưa được khởi tạo và biên dịch (GCC)

giá trị của kiểu bool là một trong hai true hoặc false.

Bây giờ xem xét mã này,

void f(bool b) 
{ 
    switch(b) //since b is bool, it's value can be either true or false! 
    { 
     case true: cout << "possible value - true"; break; 
     case false: cout << "possible value - false"; break; 
     default: cout << "impossible value"; 
    } 
} 
int main() 
{ 
    bool b; //note : b is uninitialized 
    f(b); 
    return 0; 
} 

Compile F:\workplace>g++ test.cpp -pedantic

Run. Output:

giá trị không thể

bất ngờ đầu ra? Vâng, không thực sự, khi chỉ số Standard đọc trong chú thích của §3.9.1/6 rằng:

Sử dụng một giá trị bool trong cách mô tả bởi tiêu chuẩn quốc tế này như “không xác định”, như bằng cách kiểm tra giá trị của một đối tượng tự động uninitialized, có thể làm cho nó hoạt động như thể nó là không đúng hoặc sai.

Vì vậy, cho dù tôi biên dịch và chạy chương trình này bao nhiêu lần, tôi cũng nhận được kết quả tương tự: impossible value. Tuy nhiên, nếu tôi thay đổi nó một chút - loại bỏ các chức năng f() từ hình ảnh, và viết các khối switch trong main() bản thân:

int main() 
{ 
    bool b; //note : b is uninitialized 
    switch(b) //since b is bool, it's value can be either true or false! 
    { 
     case true: cout << "possible value - true"; break; 
     case false: cout << "possible value - false"; break; 
     default: cout << "impossible value"; 
    } 
    return 0; 
} 

Sau đó, tôi biên dịch và chạy chương trình này, tôi không nhận được impossible value như đầu ra; bất kể tôi lặp lại điều này bao nhiêu lần, tôi không bao giờ nhận được impossible value.

Tôi chỉ tò mò muốn biết tại sao thay đổi đột ngột này trong hành vi của bool chưa được khởi tạo?

Vâng, từ góc nhìn ngôn ngữ rõ ràng: hành vi không xác định. Tôi hiểu điều đó. Tôi cũng hiểu trình biên dịch là miễn phí để làm bất cứ điều gì. Tuy nhiên, từ góc độ trình biên dịch, điều này có vẻ rất thú vị đối với tôi. Trình biên dịch (tức là GCC) có thể làm gì trong mỗi trường hợp và tại sao?

Tôi đang sử dụng: g++ (GCC) 4.5.0 - MinGW, on Windows 7 Basic, 64-bit OS.

+1

Tôi không thể sao chép kết quả của bạn bằng g ++ - 4.4.5 amd64. Nhưng nếu bạn muốn trả lời cho mình những loại câu hỏi này, tại sao bạn không kiểm tra đầu ra của trình biên dịch? – BatchyX

+1

Bạn có nhận được kết quả tương tự nếu bạn bật tối ưu hóa mã không? – James

+1

Vì vậy, câu hỏi của bạn là lý do tại sao "Hành vi không xác định" là khác nhau khi tiếp xúc trong các tình huống khác nhau? Đối với ai đó biết nó là không xác định tôi không thể nghĩ ra một câu hỏi vô lý hơn! và chỉ có thể xem nó như một câu hỏi được thiết kế để thử và tạo điểm. -500 –

Trả lời

17

Tôi chỉ tò mò muốn biết tại sao thay đổi đột ngột này trong hành vi của bool chưa được khởi tạo?

Tháo rời mã và xem những gì trình biên dịch đang làm.

Đoán của tôi: vì giá trị hiện chỉ được sử dụng cục bộ, trình biên dịch tối ưu hóa nó hoàn toàn. Do hành vi là không xác định, trình biên dịch có thể an toàn chỉ giả định bất kỳ giá trị nào, ví dụ: false.Đây là một tối ưu hóa khá rõ ràng vì giá trị của b là không đổi như xa như trình biên dịch có liên quan, và toàn bộ logic của switch là dư thừa. Vì vậy, tại sao đặt nó trong thực thi?

(Điểm quan trọng ở đây thực sự là b chỉ được sử dụng cục bộ trong mã thứ hai và do đó sẽ kích hoạt tối ưu hóa hơn ngay cả trong mã chưa được tối ưu hóa. Mã đầu tiên phải được gạch chân trước khi trình biên dịch có thể thực hiện bất kỳ tối ưu hóa, hoặc các đường dẫn mã phải được truy tìm mà không phải là tầm thường).