Chỉ cần vấp phải một khẳng định, thất bại, vì nó so sánh sai với hàm returntype của một hàm, khi chính hàm trả về một bool và khẳng định không chỉ kiểm tra giá trị mà còn là kiểu của giá trị trả về. sai, để đảm bảo, rằng một bool được trả về. Bây giờ vấn đề là, C99 định nghĩa bool là _Bool và _Bool thậm chí không nhất thiết phải cùng kích thước với int (trên thực tế, theo kinh nghiệm của tôi, trên hầu hết các nền tảng ngày nay nó thường có kích thước tương tự như unsigned char), không nói về cùng loại (thực sự là không thể, vì _Bool là kiểu dựng sẵn của ngôn ngữ trong C99), nhưng xác định sai và đúng là 0 và 1 mà không có định nghĩa kiểu xếp sẵn và tiền xử lý nào mà không có kiểu nhập sẽ mặc định là int. Nếu C99 thay vào đó sẽ xác định sai và đúng như ((bool) 0) và ((bool) 1), chúng sẽ luôn là kiểu bool, không có vấn đề, làm thế nào _Bool được định nghĩa. Vì vậy, có bất kỳ lý do tốt để có chúng luôn luôn được định nghĩa là ints, ngay cả khi bool không phải là một int trên nền tảng đó hoặc là điều này chỉ là một lỗi trong ngôn ngữ, mà nên được cố định với C1x?C99 - tại sao sai và đúng được định nghĩa là 0 và 1 và không phải là ((bool) 0) và ((bool) 1)?
Trả lời
false
và true
được định nghĩa là số nguyên hằng 0
và 1
tương ứng, bởi vì đó là chính xác những gì tiêu chuẩn C99 quy định cụ thể trong phần 7.16:
< snip>
Ba macro còn lại là phù hợp để sử dụng trong #if chỉ thị tiền xử lý. Họ là
đúng
mà mở rộng đến các hằng số nguyên 1,
sai
mà mở rộng đến các hằng số nguyên 0, và
< snip>
EDIT: như các nhận xét bên dưới cho biết, có vẻ như tôi đã hiểu sai một chút câu hỏi và tôi nên cung cấp lý do tiêu chuẩn chỉ định nó như thế. Một lý do tôi có thể nghĩ, là true
và false
được cho là có thể sử dụng được trong #if
chỉ thị tiền xử lý (như báo giá từ các đề cập chuẩn).
Lý do ((bool) 0)
hoặc ((bool) 1)
sẽ không hoạt động trong #if
chỉ thị tiền xử lý, là do tiêu chuẩn không cho phép. Trong phần 6.10.1 nó nói:
Biểu thức điều khiển bao gồm điều kiện phải là một số nguyên không đổi biểu trừ rằng: nó sẽ không chứa một dàn diễn viên;
Thứ nhất, mặc dù _Bool
có thể không int
, nó là cần thiết rằng một _Bool
có thể chấp nhận các giá trị 0 và 1, do đó mở rộng true
và false
-1 và 0 là tốt.
C99 §6.2.5/2: Một đối tượng khai báo là loại _Bool là đủ lớn để lưu trữ các giá trị 0 và 1.
Ngoài ra, để tương thích ngược, true
và false
là hợp lý là int
s, bởi vì tất cả các toán tử logic đều trả lại int
.
C99 §6.5.3.3/5: Kết quả của các nhà điều hành phủ định logic
!
là 0 nếu giá trị của toán hạng của nó so sánh không công bằng 0, 1 nếu giá trị của toán hạng của nó so sánh bằng 0. Các kết quả có loạiint
. Biểu thức!E
tương đương với(0==E)
.C99 §6.5.8/6: Mỗi phòng trong số các nhà khai thác
<
(ít hơn),>
(lớn hơn),<=
(nhỏ hơn hoặc bằng), và>=
(lớn hơn hoặc bằng) sẽ mang lại 1 nếu quan hệ được chỉ định là đúng và 0 nếu nó sai. 90) Kết quả có loạiint
.C99 §6.5.9/3: Các
==
(tương đương) và!=
(không bằng) khai thác được tương tự như các nhà khai thác quan hệ trừ ưu tiên thấp hơn của họ. 91) Mỗi toán tử mang lại 1 nếu quan hệ được chỉ định là đúng và 0 nếu nó sai. Kết quả có loạiint
. Đối với bất kỳ cặp toán hạng nào, chính xác một trong các quan hệ là đúng.C99 §6.5.13/3: Nhà điều hành
&&
phải mang lại 1 nếu cả hai toán hạng của nó so sánh không bằng 0; nếu không, nó mang lại 0. Kết quả có loạiint
.C99 §6.5.14/3: Toán tử
||
sẽ mang lại 1 nếu một trong hai toán hạng của nó so sánh không bằng 0; nếu không, nó mang lại 0. Kết quả có loạiint
.
Và cuối cùng, như @Sander De Dycker đề cập, tiêu chuẩn định nghĩa true
và false
được mở rộng như thế (C99 §7.16/3).
Nhưng bạn thường sẽ kiểm tra các toán tử logic mà không sử dụng đúng hay sai và viết mã như "if (foo) "và" if (! foo) "(vì triển khai-specif TRUE-macro, nó chỉ được đảm bảo! = FALSE, nhưng không phải là 1, và nếu bạn viết mã như" if (foo == true) ", sau đó bạn có thể vô tình có được thói quen đó cho TRUE). Ngoài ra nếu tránh các toán tử ẩn khi so sánh kết quả toán tử logic với true/false sẽ là vấn đề, sau đó lưu các kết quả này vào bool hoặc kiểm tra bool với true/false sẽ có cùng một vấn đề và tốt nhất cho tiêu chuẩn để xác định bool như int. – Kaiserludi
Ngoài những lý do khác đã được đề cập, bởi vì _Bool
sẽ trở thành int
ngay khi bạn thực hiện hầu hết mọi thứ với nó. Ví dụ, loại (_Bool)0 & (_Bool)1
là gì? Bạn có thể nghĩ rằng biểu thức có kiểu _Bool
, nhưng thực sự §6.5.10 xác định ngữ nghĩa của &
:
... Quá trình chuyển đổi số học thông thường được thực hiện trên các toán hạng ...
" chuyển đổi số học thông thường "có ý nghĩa rất cụ thể trong tiêu chuẩn C. Nó được định nghĩa trong §6.3.1.8, và bao gồm những điều sau đây:
... chương trình khuyến mãi số nguyên được thực hiện trên cả hai toán hạng ...
"chương trình khuyến mãi số nguyên" cũng là một thuật ngữ được định nghĩa, từ §6.3.1.1:
Nếu int có thể đại diện cho tất cả các giá trị của loại gốc, giá trị được chuyển đổi thành int; nếu không, nó sẽ được chuyển thành int không dấu. Đây được gọi là số lượng khuyến mãi.48) Tất cả các loại khác không thay đổi theo các chương trình khuyến mãi số nguyên.
Mặc dù loại hẹp hơn int
tồn tại trong tiêu chuẩn C, chúng tự động được mở rộng thành int
ở gần như bất kỳ biểu thức nào. Cùng với thực tế là kết quả của các hoạt động boolean có loại int
, điều này làm cho int
là một lựa chọn tự nhiên cho loại của các chữ này.
Tất cả các câu trả lời khác đang cố gắng sử dụng tiêu chuẩn để biện minh cho lý do tại sao tiêu chuẩn xác định mọi thứ theo một cách nhất định mà tôi thấy không đạt yêu cầu. Tiêu chuẩn xác định không chỉ các kiểu, mà còn là toán tử và tiền xử lý, vì vậy nếu C99 giới thiệu kiểu Boolean, tại sao không thay đổi tất cả toán tử Boolean để đánh giá giá trị kiểu đó và mở rộng bộ tiền xử lý để hỗ trợ kiểu Boolean?
Để làm như vậy sẽ có thể, nhưng phức tạp hơn cần thiết. Nó dễ dàng hơn nhiều đối với các nhà văn tiêu chuẩn và các nhà biên dịch-biên dịch để chỉ thực hiện các thay đổi tối thiểu cần thiết để thêm một kiểu Boolean mới vào ngôn ngữ. Vì tất cả các thao tác Boolean vẫn đánh giá để loại int
, tất cả các trình biên dịch trước C99 có thể được cập nhật để hỗ trợ C99 mà không phải thay đổi mã đánh giá kiểu của họ cho tất cả các toán tử cơ bản, và các nhà văn tiêu chuẩn có thể tự tin hơn Tính năng Boolean đã không vô tình giới thiệu mâu thuẫn với các phần của tiêu chuẩn mà trước đó đã được sử dụng tốt. Tất cả những gì họ cần làm là đảm bảo "chuyển đổi số học thông thường" được áp dụng cho _Bool
và sau đó mọi thứ khác được đảm bảo hoạt động.
Đó không phải là lý do kỹ thuật. Đó là một thực tế.
- 1. Là 0 và! 1 tốt hơn 1 và 0?
- 2. BOOL và tinyint (1) ... chưa được ký?
- 3. Tại sao 0 && 1 là 1 trong khi 1 && 0 bằng 0 trong ruby?
- 4. Tại sao ~ 0 là -1?
- 5. Là 0 và! 1 cái gì đó hơn là viết tắt cho đúng/sai?
- 6. Giá trị bit trả về là 1/0 và KHÔNG đúng/sai trong SQL Server
- 7. C++ bool trả về 0 1 thay vì false false
- 8. Chuyển đổi.ToBoolean và Boolean.Parse không chấp nhận 0 và 1
- 9. Tại sao quá tải đúng và sai thay vì xác định toán tử bool?
- 10. $ (0) và $ (1) được sử dụng cho jQuery là gì?
- 11. Tại sao 0 là đúng nhưng sai là 1 trong vỏ?
- 12. Tại sao kết quả 2 + 1 & 0 là 0?
- 13. Trả về -1, 1 và 0 có nghĩa là gì trong mã Javascript này?
- 14. Tại sao thành ngữ đệ quy trong Haskell "'n + 1' và 'n'" và không phải là "'n' và 'n-1'"?
- 15. Tại sao (0-6) là -6 = Sai?
- 16. Cách chuyển đổi "0" và "1" thành false và true
- 17. Sự khác nhau giữa "bool" và "bool" là gì?
- 18. Trong dãy Fibonacci, là fib (0) 0 hay 1?
- 19. Tại sao Objective-C sử dụng YES và NO thay vì 1 và 0?
- 20. Hoán đổi 1 với 0 và 0 với 1 theo cách Pythonic
- 21. Có đảm bảo rằng False "là 0" và True "là 1" không?
- 22. C# trả về UInt32 so với Int32 - C# suy nghĩ 0 và 1 là Int32
- 23. Tại sao C# xử lý 0 là int và không phải là ngắn/thập phân vv?
- 24. sql boolean 0/1 Để biểu diễn đúng hoặc sai
- 25. $ _ [0], $ _ [1] trong Ruby là gì?
- 26. TryParse() - Tại sao mã này trả lại 0, kết quả không phải là -1?
- 27. Scala có cú pháp cho 0 và 1-tuple không?
- 28. ! 0 là sai trong đường ray. Tại sao?
- 29. Sự khác biệt BOOL và bool?
- 30. Khi nào BOOL và bool được sử dụng trong C++?
Câu trả lời hay, nhưng việc cung cấp một trích dẫn thực sự sẽ làm cho nó trở thành một câu trả lời tuyệt vời. – Nemo
-1 để đặt câu hỏi. –
@Nemo: khối mã chứa một trích dẫn trực tiếp từ tiêu chuẩn C99, nhưng tôi có thể đã chỉ rõ nó, và thực hiện nó như một báo giá (cố định ngay bây giờ). –