Đây là "hành vi không xác định", có nghĩa là trình biên dịch được tự do thực hiện những gì nó muốn. Nhưng "không xác định" không có nghĩa là "không giải thích được".
gì trình biên dịch được thực hiện trong trường hợp s = f
được chuyển đổi f
đầu tiên với giá trị int
65.696, và sau đó gán 65.696 đến s, mà tràn và lá 160. Trình biên dịch thực hiện điều này vì có một lệnh CPU để chuyển đổi một số dấu chấm động thành số nguyên 32 bit, nhưng không trực tiếp vào số nguyên 16 bit
Trình biên dịch đang làm với s = 65696.0F
đơn giản hơn: Biết rằng 65696.0 nằm ngoài phạm vi, vì vậy nó gán giá trị cao nhất có sẵn cho s
, xảy ra là 2^15-1 = 32767.
Bạn có thể xác minh điều này nếu bạn đọc mã lắp ráp các trình biên dịch tạo ra cho s = f (ví dụ sử dụng -S switch với gcc):
movss -4(%rbp), %xmm0 # Load float from memory into register xmm0
cvttss2si %xmm0, %eax # Convert float in xmm0 into signed 32 bit, store in eax
movw %ax, -10(%rbp) # Store lower 16 bits of eax into memory
movswl -10(%rbp), %eax # Load those 16 bits into eax, with sign extend
Các hướng dẫn cuối cùng clobbers 16 bit cao của% eax, thiết lập nó cho tất cả 0s trong trường hợp này .
gì nó tạo ra cho s = 65696.0F là đơn giản:
movw $32767, -10(%rbp) # Store the lower 16 bits of 32767 into memory
movswl -10(%rbp), %eax # Load those 16 bits into eax, with sign extend
+1. Cụ thể, 6.3.1.4/1: * "Khi một giá trị hữu hạn của kiểu thả nổi thực được chuyển đổi thành một kiểu số nguyên khác với _Bool, phần phân số bị loại bỏ (nghĩa là giá trị được cắt ngắn về 0). một phần không thể được biểu diễn bằng kiểu số nguyên, hành vi không xác định) "* – Jon
@Jon Vậy tại sao không cùng một điều xảy ra khi tôi nói' f = 65696.0F; s = f'? – rootkea
@rootkea đây là hành vi không xác định là tốt và vâng hành vi không xác định có thể không đoán trước được. – ouah