2017-10-16 18 views
28

C11 §6.5.7 Khoản 5:Là "-1 >> 5;" hành vi không xác định trong C?

Kết quả của E1 >> E2E1 vị trí E2 chút phải thay đổi. Nếu E1 có loại chưa ký hoặc nếu E1 có loại đã ký và giá trị không âm, , giá trị của kết quả là phần không tách rời của số thương số E1/2*^E2. Nếu E1 có loại đã ký và giá trị âm, giá trị kết quả được xác định thực hiện.

Nhưng, Tài liệu tham khảo viva64 nói:

int B; 
B = -1 >> 5; // unspecified behavior 

tôi chạy mã này vào GCC và nó luôn luôn đưa ra một sản lượng -1.

Vì vậy, tiêu chuẩn nói rằng "Nếu E1 có một loại chữ ký và một giá trị âm, giá trị kết quả là thực hiện xác định", Nhưng tài liệu mà nói rằng -1>>5;không xác định hành vi.

Vì vậy, là -1>>5; hành vi không xác định trong C? Đó là chính xác?

+17

Nếu bạn đang cố gắng viết mã di động, sự khác biệt giữa việc triển khai được xác định và không xác định không phải là rất đáng kể, vì vậy các trình kiểm tra mã xử lý chúng tương tự. – Barmar

+1

Nó được thực hiện xác định. – chux

+0

@chux Vì vậy, tài liệu đó không đúng? – rsp

Trả lời

33

Cả hai đều chính xác. Hành vi được xác định thực hiện là một loại hành vi không xác định cụ thể.

Trích dẫn phần 3.4.1 của the C standard trong đó xác định "hành vi thực hiện xác định":

hành vi thực hiện xác định

hành vi không xác định nơi mà mỗi văn bản thực hiện như thế nào lựa chọn được thực hiện

VÍ DỤ Ví dụ về hành vi được thực hiện được xác định là t ông tuyên truyền bit thứ tự cao khi số nguyên đã ký được dịch chuyển sang phải.

Từ phần 3.4.4 quy định "hành vi không xác định":

hành vi không xác định

sử dụng một giá trị không xác định, hoặc hành vi khác nơi tiêu chuẩn quốc tế này cung cấp hai hoặc nhiều khả năng hơn và áp đặt không yêu cầu thêm nào được chọn trong bất kỳ trường hợp nào

VÍ DỤ Ví dụ về hành vi không xác định là thứ tự các đối số cho một hàm được đánh giá.

Đối với GCC, bạn sẽ luôn nhận được cùng một câu trả lời vì thao tác được thực hiện xác định. Nó thực hiện sự thay đổi bên phải của số âm qua phần mở rộng dấu

Từ GCC documentation:

Kết quả của một số hoạt động Bitwise trên số nguyên ký (C90 6.3, C99 và C11 6.5).

Các toán tử bit hoạt động trên giá trị bao gồm cả bit dấu và giá trị, trong đó bit dấu được coi là ngay trên giá trị giá trị cao nhất. Đã ký >> hoạt động trên số âm bằng tiện ích dấu.

Là một phần mở rộng của ngôn ngữ C, GCC không sử dụng một vĩ độ trong C99 và C11 chỉ để điều trị một số khía cạnh của ký << như không xác định. Tuy nhiên, -fsanitize=shift (và -fsanitize=undefined) sẽ chẩn đoán các trường hợp như vậy. Chúng cũng được chẩn đoán khi có các biểu thức hằng số .

+1

Điều này không hoàn toàn chính xác: "Hành vi được xác định thực hiện là một kiểu hành vi không xác định cụ thể". Nếu một hành vi được xác định thực hiện, tiêu chuẩn xác định rằng việc triển khai phải xác định và ghi lại nó, vì vậy nó không được chỉ định. Hành vi không xác định là dành cho các tình huống mà việc triển khai tự do lựa chọn nhưng không phải ghi lại hành vi hoặc làm cho nó phù hợp. –

+7

@R .. Ngoại trừ định nghĩa "hành vi được xác định thực hiện" thực sự sử dụng các từ chính xác "hành vi không xác định". Tôi đoán yêu cầu tài liệu không được coi là áp đặt "các yêu cầu khác được chọn". – aschepler

+1

Tôi sẽ diễn giải định nghĩa "hành vi được xác định thực hiện" mà bạn trích dẫn là độc quyền của "hành vi không xác định", nghĩa là "đối với hành vi không xác định, mà còn với yêu cầu này". Sau khi tất cả, định nghĩa "hành vi không xác định" bao gồm "không áp đặt thêm yêu cầu nào được chọn", tuy nhiên hành vi được thực hiện xác định yêu cầu rằng tài liệu thực hiện lựa chọn, do đó nó không đáp ứng định nghĩa "hành vi không xác định" –

12

"Hành vi không xác định" và "triển khai được xác định" không mâu thuẫn. Nó chỉ có nghĩa là tiêu chuẩn C không xác định những gì cần phải xảy ra, và việc triển khai khác nhau có thể làm những gì họ cho là "đúng".

Chạy nhiều lần trên một trình biên dịch và nhận kết quả tương tự chỉ có nghĩa là trình biên dịch cụ thể nhất quán. Bạn có thể nhận được kết quả khác nhau trên một trình biên dịch khác nhau.

+1

Không có thuật ngữ nào là tập hợp con của cụm từ kia. Nếu một hành động gọi hành vi "không xác định", thì cần phải triển khai thực hiện để chọn trong số một tập hợp các lựa chọn hữu hạn (ví dụ:'x() + y()' phải hoạt động như thể nó đánh giá đầy đủ 'x()' và sau đó đánh giá 'y()', hoặc đầy đủ 'y()' và sau đó là 'x()'; đó là hai lựa chọn duy nhất). Nếu một hành động gọi hành vi "Thực hiện xác định", việc triển khai được yêu cầu để ghi lại hành vi cụ thể, nhưng có thể làm bất kỳ thứ gì họ thích miễn là chúng ghi lại. – supercat

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