C không có bất kỳ loại boolean tích hợp nào. Cách tốt nhất để sử dụng chúng trong C là gì?
C không có bất kỳ loại boolean tích hợp nào. Cách tốt nhất để sử dụng chúng trong C là gì?
Câu trả lời:
Từ tốt nhất đến tồi tệ hơn:
Tùy chọn 1 (C99)
#include <stdbool.h>
Lựa chọn 2
typedef enum { false, true } bool;
Lựa chọn 3
typedef int bool;
enum { false, true };
Lựa chọn 4
typedef int bool;
#define true 1
#define false 0
Nếu bạn chưa quyết định, hãy đi với # 1!
<stdbool.h> booltrình biên dịch chọn có thể phù hợp hơn cho mục đích dự định của giá trị boolean hơn là sử dụng một int(tức là trình biên dịch có thể chọn thực hiện boolkhác với một int). Nó cũng có thể dẫn đến việc kiểm tra loại chặt chẽ hơn vào thời gian biên dịch, nếu bạn may mắn.
intcho bool? Điều đó thật lãng phí. Sử dụng unsigned char. Hoặc sử dụng được xây dựng trong C _Bool.
Một vài suy nghĩ về booleans trong C:
Tôi đã đủ tuổi để tôi chỉ sử dụng ints đơn giản làm kiểu boolean của mình mà không có bất kỳ typedefs hoặc định nghĩa đặc biệt hoặc enum nào cho các giá trị đúng / sai. Nếu bạn làm theo đề xuất của tôi dưới đây về việc không bao giờ so sánh với các hằng số boolean, thì bạn chỉ cần sử dụng 0/1 để khởi tạo các cờ. Tuy nhiên, cách tiếp cận như vậy có thể được coi là quá phản động trong thời hiện đại này. Trong trường hợp đó, người ta chắc chắn nên sử dụng <stdbool.h>vì ít nhất nó có lợi ích của việc được tiêu chuẩn hóa.
Dù các hằng số boolean được gọi là gì, chỉ sử dụng chúng để khởi tạo. Không bao giờ viết một cái gì đó như
if (ready == TRUE) ...
while (empty == FALSE) ...
Chúng luôn có thể được thay thế bởi rõ ràng hơn
if (ready) ...
while (!empty) ...
Lưu ý rằng những điều này thực sự có thể hợp lý và dễ hiểu được đọc thành tiếng.
Đặt tên biến boolean của bạn tên tích cực, tức là fullthay vì notfull. Cái sau dẫn đến mã khó đọc dễ dàng. Đối chiếu
if (full) ...
if (!full) ...
với
if (!notfull) ...
if (notfull) ...
Cả hai cặp trước đây đọc tự nhiên, trong khi !notfullrất khó đọc ngay cả khi nó, và trở nên tồi tệ hơn nhiều trong các biểu thức boolean phức tạp hơn.
Đối số Boolean thường nên tránh. Hãy xem xét một hàm được định nghĩa như thế này
void foo(bool option) { ... }
Trong phần thân của hàm, rất rõ ràng đối số có nghĩa là gì vì nó có một tên thuận tiện và hy vọng có ý nghĩa. Nhưng, các trang web cuộc gọi trông giống như
foo(TRUE);
foo(FALSE):
Ở đây, về cơ bản không thể nói tham số có nghĩa là gì mà không luôn luôn nhìn vào định nghĩa hoặc khai báo hàm và nó sẽ trở nên tồi tệ hơn ngay khi bạn thêm các tham số boolean thậm chí nhiều hơn. Tôi đề nghị một trong hai
typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);
hoặc là
#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }
Trong cả hai trường hợp, trang web cuộc gọi bây giờ trông giống như
foo(OPT_ON);
foo(OPT_OFF);
mà người đọc có ít nhất một cơ hội để hiểu mà không cần nạo vét định nghĩa foo.
a == blàm việc?
avà btính từ 0, tôi khuyên bạn nên a > 0 == b > 0thay thế. Nếu bạn khăng khăng lợi dụng tính trung thực của các giá trị khác không tùy ý, !!varsẽ mang lại giá trị 0/1 tương đương var, vì vậy bạn có thể viết !!a == !!b, mặc dù khá nhiều độc giả sẽ thấy khó hiểu.
!a == !bcũng đủ để kiểm tra sự bằng nhau, các số không trở thành số không và số không trở thành số một.
!!alà "chuyển đổi không boolean a thành giá trị thật tương đương của nó", trong khi tôi đọc !alà "đảo ngược biến boolean a". Cụ thể, tôi tìm kiếm một số lý do cụ thể mà sự đảo ngược logic được mong muốn.
Một boolean trong C là một số nguyên: 0 cho false và khác không cho true.
Xem thêm Kiểu dữ liệu Boolean , phần C, C ++, Objective-C, AWK .
Đây là phiên bản mà tôi đã sử dụng:
typedef enum { false = 0, true = !false } bool;
Bởi vì false chỉ có một giá trị, nhưng một logic đúng có thể có nhiều giá trị, nhưng kỹ thuật đặt đúng là những gì trình biên dịch sẽ sử dụng cho ngược lại với false.
Điều này quan tâm đến vấn đề ai đó mã hóa thứ gì đó sẽ xảy ra:
if (true == !false)
Tôi nghĩ rằng tất cả chúng ta sẽ đồng ý rằng đó không phải là một thực tiễn tốt, nhưng với chi phí một lần để làm "đúng =! Sai", chúng tôi loại bỏ vấn đề đó.
[EDIT] Cuối cùng tôi đã sử dụng:
typedef enum { myfalse = 0, mytrue = !myfalse } mybool;
để tránh xung đột tên với các chương trình khác đã được xác định truevà false. Nhưng khái niệm vẫn giữ nguyên.
[EDIT] Để hiển thị chuyển đổi số nguyên sang boolean:
mybool somebool;
int someint = 5;
somebool = !!someint;
Đầu tiên (đúng nhất)! chuyển đổi số nguyên khác không thành 0, sau đó là số thứ hai (hầu hết bên trái)! chuyển đổi 0 thành một myfalsegiá trị. Tôi sẽ để nó như một bài tập cho người đọc để chuyển đổi một số nguyên bằng không.
[EDIT] Phong cách của tôi là sử dụng cài đặt rõ ràng của một giá trị trong enum khi giá trị cụ thể được yêu cầu ngay cả khi giá trị mặc định sẽ giống nhau. Ví dụ: Bởi vì sai cần bằng 0 nên tôi sử dụng false = 0,chứ không phảifalse,
true, falsevà boolđược làm nổi bật trong hầu hết các IDE vì họ là những giá trị enum và một typedef, như trái ngược với #defines, đó là hiếm khi cú pháp tô sáng.
gcc -ansi -pedantic -Wallkhông đưa ra cảnh báo, vì vậy tôi tin tưởng gcc; Nếu điều này làm việc ngay cả cho c89nó sẽ làm việc cho c99aswell.
!chỉ có thể trả về các giá trị 0và 1vì vậy true = !falsesẽ luôn gán giá trị 1. Phương thức này không cung cấp bất kỳ sự an toàn bổ sung nào typedef enum { false, true } bool;.
if(!value)), nhưng ngoại lệ đó không được áp dụng trong trường hợp cụ thể này.
Nếu bạn đang sử dụng trình biên dịch C99, nó có hỗ trợ tích hợp cho các loại bool:
#include <stdbool.h>
int main()
{
bool b = false;
b = true;
}
Điều đầu tiên đầu tiên. C, tức là ISO / IEC 9899 đã có kiểu boolean từ 19 năm nay . Đó là thời gian dài hơn thời gian dự kiến của sự nghiệp lập trình C với các phần nghiệp dư / học thuật / chuyên nghiệp kết hợp khi truy cập câu hỏi này . Của tôi không vượt qua điều đó có lẽ chỉ 1-2 năm. Điều đó có nghĩa là trong suốt thời gian mà một người đọc trung bình đã học được bất cứ điều gì về C, C thực sự đã có kiểu dữ liệu boolean .
Đối với kiểu dữ liệu #include <stdbool.h>, và sử dụng true, falsevà bool. Hoặc không bao gồm nó, và sử dụng _Bool, 1và 0thay vào đó.
Có nhiều thực hành nguy hiểm khác nhau được thúc đẩy trong các câu trả lời khác cho chủ đề này. Tôi sẽ giải quyết chúng:
typedef int bool;
#define true 1
#define false 0
Điều này là không, bởi vì một người đọc bình thường - người đã học C trong vòng 19 năm đó - sẽ mong đợi điều đó boolđề cập đến kiểu dữ liệu thực tế bool và sẽ hành xử tương tự, nhưng không! Ví dụ
double a = ...;
bool b = a;
Với C99 bool/ _Bool, bsẽ được đặt thành false iff a bằng 0 và truengược lại. C11 6.3.1.2p1
- Khi bất kỳ giá trị vô hướng nào được chuyển đổi thành
_Bool, kết quả là 0 nếu giá trị so sánh bằng 0; mặt khác, kết quả là 1. 59)Chú thích
59) NaN không so sánh bằng 0 và do đó chuyển đổi thành 1.
Với typedefvị trí, doublesẽ bị ép buộc thành một int- nếu giá trị của số kép không nằm trong phạm vi cho int, thì hành vi không được xác định .
Đương nhiên áp dụng tương tự cho nếu truevà falseđược khai báo trong một enum.
Điều thậm chí còn nguy hiểm hơn là tuyên bố
typedef enum bool {
false, true
} bool;
bởi vì bây giờ tất cả các giá trị ngoài 1 và 0 đều không hợp lệ và nếu giá trị đó được gán cho một biến của loại đó, thì hành vi sẽ hoàn toàn không được xác định .
Do đó, nếu bạn không thể sử dụng C99 vì một số lý do không thể giải thích được, đối với các biến boolean bạn nên sử dụng:
intvà các giá trị 0và 1 nguyên trạng ; và cẩn thận thực hiện chuyển đổi tên miền từ bất kỳ giá trị nào khác sang giá trị này với phủ định kép!!BOOL, TRUEvà FALSE!inthoặc unsigned intđể liệt kê, nhưng tôi không biết gì trong Tiêu chuẩn sẽ khiến phép liệt kê hoạt động như bất kỳ thứ gì ngoài số nguyên kiểu.
typedef enum {
false = 0,
true
} t_bool;
!0 = 1theo tiêu chuẩn C và !a = 0với bất kỳ giá trị khác không nào của a. Vấn đề là bất kỳ số không nào cũng được coi là đúng. Vì vậy, nếu avà bcả hai đều "đúng", thì không nhất thiết phải là `a == b`.
C có loại boolean: bool (ít nhất là trong 10 (!) Năm qua)
Bao gồm stdbool.h và true / false sẽ hoạt động như mong đợi.
boolphải là một macro mở rộng _Bool. Sự khác biệt quan trọng bởi vì bạn có thể #undefmột macro (và điều đó được cho phép, ít nhất là như một biện pháp chuyển tiếp), nhưng bạn không thể untypedeflà một typedef. Tuy nhiên, nó không làm thay đổi lực đẩy chính của bình luận đầu tiên của bạn.
Bất cứ điều gì khác không được đánh giá là đúng trong các hoạt động boolean, vì vậy bạn chỉ có thể
#define TRUE 1
#define FALSE 0
và sử dụng các hằng số.
Chỉ cần bổ sung cho các câu trả lời khác và một số làm rõ, nếu bạn được phép sử dụng C99.
+-------+----------------+-------------------------+--------------------+
| Name | Characteristic | Dependence in stdbool.h | Value |
+-------+----------------+-------------------------+--------------------+
| _Bool | Native type | Don't need header | |
+-------+----------------+-------------------------+--------------------+
| bool | Macro | Yes | Translate to _Bool |
+-------+----------------+-------------------------+--------------------+
| true | Macro | Yes | Translate to 1 |
+-------+----------------+-------------------------+--------------------+
| false | Macro | Yes | Translate to 0 |
+-------+----------------+-------------------------+--------------------+
Một số sở thích của tôi:
_Boolhay bool? Cả hai đều tốt, nhưng booltrông tốt hơn so với từ khóa _Bool.boolvà _Boollà: falsehoặc true. Chỉ định 0hoặc 1thay vì falsehoặc truehợp lệ, nhưng khó đọc và hiểu luồng logic hơn.Một số thông tin từ tiêu chuẩn:
_Boollà KHÔNG unsigned int, nhưng là một phần của các kiểu số nguyên không dấu nhóm . Nó đủ lớn để giữ các giá trị 0hoặc 1.bool truevà falsechắc chắn đó không phải là một ý tưởng tốt. Khả năng này được coi là lỗi thời và sẽ bị loại bỏ trong tương lai._Boolhoặc bool, nếu giá trị vô hướng bằng 0hoặc so sánh với 0nó 0, nếu không, kết quả là 1: _Bool x = 9; 9được chuyển đổi thành 1khi được gán cho x._Boollà 1 byte (8 bit), thông thường lập trình viên cố gắng sử dụng các bit khác, nhưng không được khuyến khích, vì điều duy nhất được đảm bảo là chỉ sử dụng một bit để lưu trữ dữ liệu, không giống như loại charcó 8 bit có sẵn.Bạn có thể sử dụng char, hoặc một container số nhỏ khác cho nó.
Mã giả
#define TRUE 1
#define FALSE 0
char bValue = TRUE;
int), vì trên một số kiến trúc, bạn nhận được một hiệu suất đáng kể từ việc phải giải nén / mặt nạ kiểm tra các biến này.
Bạn có thể sử dụng _Bool, nhưng giá trị trả về phải là số nguyên (1 cho đúng, 0 cho sai). Tuy nhiên, nên bao gồm và sử dụng bool như trong C ++, như đã nói trong bài trả lời này từ diễn đàn daniweb , cũng như câu trả lời này , từ câu hỏi stackoverflow khác này:
_Bool: Kiểu boolean của C99. Chỉ nên sử dụng _Bool trực tiếp nếu bạn đang duy trì mã kế thừa đã xác định macro cho bool, true hoặc false. Mặt khác, các macro đó được tiêu chuẩn hóa trong tiêu đề. Bao gồm tiêu đề đó và bạn có thể sử dụng bool giống như trong C ++.
Các biểu thức điều kiện được coi là đúng nếu chúng khác không, nhưng tiêu chuẩn C yêu cầu các toán tử logic tự trả về 0 hoặc 1.
@Tom: #define TRUE! FALSE là xấu và hoàn toàn vô nghĩa. Nếu tệp tiêu đề đi vào mã C ++ được biên dịch, thì nó có thể dẫn đến các vấn đề:
void foo(bool flag);
...
int flag = TRUE;
foo(flag);
Một số trình biên dịch sẽ tạo cảnh báo về chuyển đổi int => bool. Đôi khi mọi người tránh điều này bằng cách làm:
foo(flag == TRUE);
để buộc biểu thức là một bool C ++. Nhưng nếu bạn #define TRUE! FALSE, bạn sẽ kết thúc với:
foo(flag == !0);
kết thúc bằng cách so sánh int-to-bool có thể kích hoạt cảnh báo bằng mọi cách.
Nếu bạn đang sử dụng C99 thì bạn có thể sử dụng _Boolloại. Không #includecần thiết. Bạn không cần phải đối xử với nó như một số nguyên, tuy nhiên, ở đâu 1là truevà 0là false.
Sau đó bạn có thể định nghĩa TRUEvà FALSE.
_Bool this_is_a_Boolean_var = 1;
//or using it with true and false
#define TRUE 1
#define FALSE 0
_Bool var = TRUE;
#include <stdbool.h>sử dụng bool, truevà falsenhư tiêu chuẩn muốn bạn.
Đây là những gì tôi sử dụng:
enum {false, true};
typedef _Bool bool;
_Bool là một kiểu dựng sẵn trong C. Nó dành cho các giá trị boolean.
Bạn chỉ có thể sử dụng lệnh #definenhư sau:
#define TRUE 1
#define FALSE 0
#define NOT(arg) (arg == TRUE)? FALSE : TRUE
typedef int bool;
Và sử dụng như sau:
bool isVisible = FALSE;
bool isWorking = TRUE;
isVisible = NOT(isVisible);
và như thế
argvà toàn bộ biểu thức : #define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE). Tuy nhiên, sẽ tốt hơn nếu kiểm tra độ giả (nó sẽ cho câu trả lời đúng ngay cả khi arglà 23 thay vì 0 hoặc 1. #define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE)Nhưng tất nhiên, toàn bộ biểu thức có thể được giảm xuống #define NOT(arg) (!(arg)), tất nhiên, tạo ra kết quả tương tự.