2011-07-08 48 views
5

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

8

falsetrue được định nghĩa là số nguyên hằng 01 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à truefalse đượ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;

+0

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

+0

-1 để đặt câu hỏi. –

+0

@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ờ). –

2

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 truefalse-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, truefalse 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ại int. 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ại int.

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ại int. Đố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ại int.

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ại int.

Và cuối cùng, như @Sander De Dycker đề cập, tiêu chuẩn định nghĩa truefalse được mở rộng như thế (C99 §7.16/3).

+0

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

4

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.

+0

tại sao bạn sẽ sử dụng nhị phân AND trên hai boolean? – dascandy

+1

@dascandy: Toàn bộ bên cạnh điểm. Bên cạnh đó, tại sao không? –

+1

@dascandy: Điều gì sẽ xảy ra nếu hai toán hạng là các hàm gọi trả về '_Bool' và nếu hàm này có các tác dụng phụ mà bạn không muốn bị mất mạch ngắn? – jamesdlin

1

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ế.

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