C ไม่มีบูลีนในตัวชนิดใด ๆ วิธีที่ดีที่สุดที่จะใช้ใน C คืออะไร?
C ไม่มีบูลีนในตัวชนิดใด ๆ วิธีที่ดีที่สุดที่จะใช้ใน C คืออะไร?
คำตอบ:
จากดีที่สุดถึงแย่กว่า:
ตัวเลือก 1 (C99)
#include <stdbool.h>
ตัวเลือก 2
typedef enum { false, true } bool;
ตัวเลือก 3
typedef int bool;
enum { false, true };
ตัวเลือก 4
typedef int bool;
#define true 1
#define false 0
หากคุณยังไม่แน่ใจให้ไปที่ # 1!
<stdbool.h>
bool
คอมไพเลอร์เลือกอาจเหมาะสมกว่าสำหรับวัตถุประสงค์ที่ตั้งใจไว้ของค่าบูลีนมากกว่าการใช้int
(เช่นคอมไพเลอร์อาจเลือกใช้งานที่bool
แตกต่างจากint
) นอกจากนี้ยังอาจส่งผลให้การตรวจสอบประเภทที่เข้มงวดยิ่งขึ้นในเวลารวบรวมหากคุณโชคดี
int
สำหรับbool
? นั่นช่างสิ้นเปลือง unsigned char
ใช้ _Bool
หรือใช้ในตัวของ C
ความคิดเล็กน้อยเกี่ยวกับบูลีนใน C:
ฉันแก่พอที่ฉันจะใช้int
s ธรรมดาเป็นประเภทบูลของฉันโดยไม่มีการพิมพ์หรือกำหนดหรือ enums พิเศษสำหรับค่าจริง / เท็จ หากคุณทำตามคำแนะนำของฉันด้านล่างนี้อย่าเปรียบเทียบกับค่าคงที่บูลีนคุณจะต้องใช้ 0/1 เพื่อเริ่มต้นค่าสถานะอย่างไรก็ตาม อย่างไรก็ตามวิธีการดังกล่าวอาจถือว่าเป็นปฏิกิริยาเกินไปในยุคปัจจุบันเหล่านี้ ในกรณีนี้เราควรใช้อย่างแน่นอน<stdbool.h>
เพราะอย่างน้อยก็มีประโยชน์ในการเป็นมาตรฐาน
ไม่ว่าค่าคงที่บูลีนจะถูกเรียกให้ใช้มันเพื่อการเริ่มต้นเท่านั้น ไม่เคยเขียนอะไรเช่น
if (ready == TRUE) ...
while (empty == FALSE) ...
สิ่งเหล่านี้สามารถถูกแทนที่ได้โดยชัดเจนยิ่งขึ้น
if (ready) ...
while (!empty) ...
โปรดทราบว่าสิ่งเหล่านี้สามารถอ่านออกมาได้อย่างสมเหตุสมผลและสมเหตุสมผล
ให้ตัวแปรบูลของคุณชื่อในเชิงบวกคือแทนfull
notfull
หลังนำไปสู่รหัสที่อ่านยาก เปรียบเทียบ
if (full) ...
if (!full) ...
กับ
if (!notfull) ...
if (notfull) ...
คู่ก่อนหน้าทั้งคู่อ่านอย่างเป็นธรรมชาติในขณะ!notfull
ที่อ่านได้ไม่สะดวกเท่าที่ควร
โดยทั่วไปแล้วควรหลีกเลี่ยงการโต้แย้งบูลีน พิจารณาฟังก์ชั่นที่กำหนดเช่นนี้
void foo(bool option) { ... }
ภายในเนื้อความของฟังก์ชั่นมันชัดเจนมากว่าอาร์กิวเมนต์หมายถึงอะไรเพราะมีชื่อที่สะดวกและมีความหมาย แต่ไซต์การโทรดูเหมือนว่า
foo(TRUE);
foo(FALSE):
ที่นี่เป็นไปไม่ได้เลยที่จะบอกว่าพารามิเตอร์มีความหมายอย่างไรโดยไม่ได้ดูนิยามของฟังก์ชั่นหรือการประกาศอยู่เสมอ ฉันขอแนะนำอย่างใดอย่างหนึ่ง
typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);
หรือ
#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }
ไม่ว่าในกรณีใดไซต์โทรจะมีลักษณะเช่นนี้
foo(OPT_ON);
foo(OPT_OFF);
foo
ซึ่งผู้อ่านมีอย่างน้อยโอกาสของความเข้าใจโดยไม่ต้องขุดลอกขึ้นความหมายของการเป็น
a == b
ทำงาน
a
และb
นับจากศูนย์ฉันขอแนะนำa > 0 == b > 0
แทน หากคุณยืนยันในการใช้ประโยชน์จากความเป็นจริงของค่าที่ไม่เป็นศูนย์โดยพลการให้ค่า!!var
บูลีน 0/1 เทียบเท่ากับvar
ดังนั้นคุณสามารถเขียน!!a == !!b
แม้ว่าผู้อ่านจำนวนน้อยจะรู้สึกสับสน
!a == !b
ก็เพียงพอสำหรับการทดสอบความเท่าเทียมกันไม่ใช่ศูนย์กลายเป็นศูนย์และศูนย์กลายเป็นหนึ่ง
!!a
ว่า "แปลงไม่ใช่บูลีนเป็นค่าความจริงที่เทียบเท่ากัน" ในขณะที่ฉันอ่าน!a
ว่า "เปลี่ยนตรรกะบูลีนเป็นตรรกะ" โดยเฉพาะฉันต้องการเหตุผลบางอย่างที่ต้องการการผกผันแบบตรรกะ
บูลีนใน C เป็นจำนวนเต็ม: ศูนย์สำหรับเท็จและไม่เป็นศูนย์สำหรับจริง
ดูเพิ่มเติมชนิดข้อมูลแบบบูลส่วนC, C ++, Objective-C, AWK
นี่คือรุ่นที่ฉันใช้:
typedef enum { false = 0, true = !false } bool;
เนื่องจาก false มีเพียงค่าเดียว แต่ตรรกะจริงอาจมีหลายค่าได้ แต่เทคนิคกำหนดให้เป็นสิ่งที่คอมไพเลอร์จะใช้สำหรับตรงกันข้ามกับ false
สิ่งนี้จะดูแลปัญหาของคนที่เข้ารหัสสิ่งที่จะลงมา:
if (true == !false)
ฉันคิดว่าเราทุกคนเห็นด้วยว่านั่นไม่ใช่วิธีปฏิบัติที่ดี แต่สำหรับค่าใช้จ่ายครั้งเดียวในการทำ "true =! false" เรากำจัดปัญหานั้น
[แก้ไข] ในที่สุดฉันใช้:
typedef enum { myfalse = 0, mytrue = !myfalse } mybool;
เพื่อหลีกเลี่ยงการชนชื่อกับแผนการอื่นที่กำหนดtrue
และfalse
และแต่แนวคิดยังคงเหมือนเดิม
[แก้ไข] วิธีแสดงการแปลงจำนวนเต็มเป็นบูลีน:
mybool somebool;
int someint = 5;
somebool = !!someint;
ครั้งแรก (ขวาสุด)! แปลงจำนวนเต็มที่ไม่ใช่ศูนย์เป็น 0 จากนั้นเป็นวินาที (เหลือมากที่สุด)! แปลง 0 เป็น amyfalse
ค่า ฉันจะปล่อยให้มันเป็นแบบฝึกหัดให้ผู้อ่านแปลงจำนวนเต็มเป็นศูนย์
[แก้ไข] มันเป็นสไตล์ของฉันที่จะใช้การตั้งค่าที่ชัดเจนของค่าใน enum เมื่อจำเป็นต้องใช้ค่าเฉพาะแม้ว่าค่าเริ่มต้นจะเหมือนกัน ตัวอย่าง: เพราะเท็จต้องเป็นศูนย์ฉันใช้false = 0,
มากกว่าfalse,
true
, false
และbool
เป็นไฮไลต์ใน IDE มากที่สุดเพราะพวกเขามีค่า enum และ typedef เป็นตรงข้ามกับ#defines
ที่ไม่ค่อยเคยไวยากรณ์ที่ไฮไลต์
gcc -ansi -pedantic -Wall
ให้คำเตือนใด ๆ ดังนั้นฉันไว้วางใจgcc
; หากใช้งานได้แม้c89
จะใช้งานc99
ได้ก็ตาม
!
เท่านั้นที่สามารถคืนค่า0
และ1
ดังนั้นtrue = !false
มักจะคุ้มค่ากำหนด 1. typedef enum { false, true } bool;
วิธีการนี้ไม่ได้ให้ความปลอดภัยพิเศษใด
if(!value)
) แต่ข้อยกเว้นนั้นไม่สามารถใช้ได้ในกรณีเฉพาะนี้
หากคุณกำลังใช้คอมไพเลอร์ C99 มันมีการรองรับในตัวสำหรับประเภทบูล:
#include <stdbool.h>
int main()
{
bool b = false;
b = true;
}
สิ่งแรกก่อน C คือมาตรฐาน ISO / IEC 9899 ได้มีชนิดบูลีนสำหรับ19 ปีในขณะนี้ นั่นคือเวลาที่นานกว่าความยาวที่คาดหวังของอาชีพการเขียนโปรแกรม C กับส่วนสมัครเล่น / วิชาการ / มืออาชีพรวมกันเมื่อเยี่ยมชมคำถามนี้ ฉันทำได้ดีกว่านี้เพียง 1-2 ปีเท่านั้น หมายความว่าในช่วงเวลาที่ผู้อ่านโดยเฉลี่ยได้เรียนรู้อะไรเกี่ยวกับ C, C จริง ๆ แล้วมีชนิดข้อมูลบูลีนจริงมีชนิดข้อมูลแบบบูล
สำหรับประเภทข้อมูล, #include <stdbool.h>
และการใช้งานtrue
, และfalse
bool
หรือไม่รวมมันและการใช้งาน_Bool
, 1
และ0
แทน
มีวิธีปฏิบัติที่เป็นอันตรายต่าง ๆที่ได้รับการส่งเสริมในคำตอบอื่น ๆ ของหัวข้อนี้ ฉันจะอยู่พวกเขา:
typedef int bool;
#define true 1
#define false 0
นี่ไม่ใช่ไม่เพราะผู้อ่านทั่วไปที่เรียนรู้ C ภายใน 19 ปีนั้นคาดว่าbool
จะอ้างอิงกับชนิดข้อมูลจริง bool
และจะทำงานในลักษณะเดียวกัน แต่ไม่ใช่! ตัวอย่างเช่น
double a = ...;
bool b = a;
ด้วย C99 bool
/ _Bool
, b
จะได้รับการตั้งค่าให้false
IFF a
เป็นศูนย์และtrue
เป็นอย่างอื่น C11 6.3.1.2p1
- เมื่อค่าสเกลาร์ใด ๆ ถูกแปลง
_Bool
เป็นผลลัพธ์จะเป็น 0 หากค่าเปรียบเทียบเท่ากับ 0 มิฉะนั้นผลลัพธ์คือ 1. 59)เชิงอรรถ
59) NaNs ไม่เปรียบเทียบเท่ากับ 0 จึงแปลงเป็น 1
กับtypedef
ในสถานที่ที่double
จะได้รับการข่มขู่ไปยังint
- ถ้าค่าของคู่ไม่ได้อยู่ในช่วงของint
การพฤติกรรมจะไม่ได้กำหนด
ธรรมชาติเช่นเดียวกับถ้าtrue
และถูกประกาศในfalse
enum
สิ่งที่อันตรายยิ่งกว่านั้นก็คือการประกาศ
typedef enum bool {
false, true
} bool;
เพราะตอนนี้ค่าทั้งหมดที่อยู่นอกเหนือจาก 1 และ 0 นั้นไม่ถูกต้องและหากค่าดังกล่าวถูกกำหนดให้กับตัวแปรประเภทนั้นพฤติกรรมจะไม่ได้ถูกกำหนดไว้อย่างสมบูรณ์
ดังนั้นถ้าคุณไม่สามารถใช้ C99 ด้วยเหตุผลบางอย่างที่อธิบายไม่ได้สำหรับตัวแปรบูลีนที่คุณควรใช้:
int
และค่า0
และ1
ตามที่เป็น ; และทำการแปลงโดเมนอย่างระมัดระวังจากค่าอื่น ๆ ถึงสิ่งเหล่านี้ด้วยการปฏิเสธคู่!!
BOOL
, TRUE
และFALSE
!int
หรือunsigned int
ถือการแจงนับ แต่ฉันรู้ว่าไม่มีอะไรใน Standard ที่จะทำให้การแจงนับเป็นสิ่งอื่นที่ไม่ใช่จำนวนเต็ม ชนิด
typedef enum {
false = 0,
true
} t_bool;
!0 = 1
โดยมาตรฐาน C และ!a = 0
สำหรับการใด ๆ a
ค่าที่ไม่ใช่ศูนย์ ปัญหาคือการใด ๆ ที่ไม่ใช่ศูนย์ถือเป็นจริง ดังนั้นถ้าa
และb
ทั้งคู่เป็น "จริง" มันไม่จำเป็นต้องเป็นกรณีที่ `a == b`
C มีประเภทบูลีน: บูล (อย่างน้อยสำหรับ 10 (!) ปี)
รวม stdbool.h และจริง / เท็จจะทำงานตามที่คาดไว้
bool
_Bool
เรื่องความแตกต่างเพราะคุณสามารถ#undef
มาโคร (และว่าได้รับอนุญาตอย่างน้อยเป็นวัดคลองท่อม) แต่คุณไม่สามารถuntypedef
typedef แม้ว่ามันจะไม่เปลี่ยนแรงผลักดันหลักของความคิดเห็นแรกของคุณ
สิ่งใดที่ไม่ใช่ศูนย์จะถูกประเมินเป็นจริงในการดำเนินการบูลีนดังนั้นคุณสามารถทำได้
#define TRUE 1
#define FALSE 0
และใช้ค่าคงที่
เป็นเพียงส่วนเติมเต็มให้กับคำตอบอื่น ๆ และชี้แจงหากคุณได้รับอนุญาตให้ใช้ 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 |
+-------+----------------+-------------------------+--------------------+
บางส่วนของการตั้งค่าของฉัน:
_Bool
หรือbool
? ทั้งคู่ใช้ได้ แต่bool
ดูดีกว่าคำหลัก_Bool
รูปลักษณ์ที่ดีกว่าคำหลักbool
และ_Bool
มีดังนี้: หรือfalse
true
การกำหนด0
หรือ1
แทนfalse
หรือtrue
ใช้ได้ แต่เป็นการยากที่จะอ่านและเข้าใจการไหลของลอจิกข้อมูลบางส่วนจากมาตรฐาน:
_Bool
ไม่ใช่unsigned int
แต่เป็นส่วนหนึ่งของกลุ่มที่ไม่มีการลงชื่อประเภทจำนวนเต็ม มันมีขนาดใหญ่พอที่จะเก็บค่า0
หรือ1
หรือbool
true
และfalse
แต่แน่ใจว่าไม่ใช่ความคิดที่ดี ความสามารถนี้ถือว่าล้าสมัยและจะถูกลบออกในอนาคต_Bool
หรือbool
ถ้าเกลาค่าเท่ากับ0
หรือเปรียบเทียบเพื่อ0
มันจะเป็น0
มิฉะนั้นผลที่ได้คือ1
: _Bool x = 9;
9
จะถูกแปลงเป็นเมื่อได้รับมอบหมายให้1
x
_Bool
คือ 1 ไบต์ (8 บิต) โดยปกติแล้วโปรแกรมเมอร์มักถูกล่อลวงให้พยายามใช้บิตอื่น แต่ไม่แนะนำเพราะสิ่งเดียวที่รับประกันคือมีเพียงหนึ่งบิตเท่านั้นที่ใช้ในการเก็บข้อมูลไม่เหมือนชนิดchar
ที่มี 8 บิตที่มีคุณสามารถใช้ถ่านหรือภาชนะขนาดเล็กจำนวนหนึ่งได้
หลอกรหัส
#define TRUE 1
#define FALSE 0
char bValue = TRUE;
int
) เนื่องจากบนสถาปัตยกรรมบางตัวที่คุณได้รับประสิทธิภาพที่สำคัญจากการตรวจสอบตัวแปร / แพ็คมาสก์
คุณสามารถใช้ _Bool ได้ แต่ค่าส่งคืนจะต้องเป็นจำนวนเต็ม (1 สำหรับจริง, 0 สำหรับเท็จ) อย่างไรก็ตามขอแนะนำให้รวมและใช้บูลเช่นเดียวกับใน C ++ ดังที่ได้กล่าวไว้ใน คำตอบนี้จากฟอรัม daniwebและคำตอบนี้จากคำถาม stackoverflow อื่น ๆ นี้:
_Bool: ประเภทบูลีนของ C99 แนะนำให้ใช้ _Bool โดยตรงในกรณีที่คุณรักษารหัสดั้งเดิมที่กำหนดมาโครสำหรับบูลจริงหรือเท็จแล้ว มิฉะนั้นมาโครเหล่านั้นจะได้มาตรฐานในส่วนหัว รวมส่วนหัวนั้นและคุณสามารถใช้บูลเหมือนใน C ++
นิพจน์แบบมีเงื่อนไขจะถือว่าเป็นจริงหากไม่ใช่ศูนย์ แต่มาตรฐาน C กำหนดให้ตัวดำเนินการเชิงตรรกะกลับมาเป็น 0 หรือ 1
@Tom: #define TRUE! FALSE ไม่ดีและไม่มีจุดหมายอย่างสมบูรณ์ หากไฟล์ส่วนหัวทำให้มันกลายเป็นรหัส C ++ รวบรวมแล้วมันสามารถนำไปสู่ปัญหา:
void foo(bool flag);
...
int flag = TRUE;
foo(flag);
คอมไพเลอร์บางตัวจะสร้างคำเตือนเกี่ยวกับการแปลง int => bool บางครั้งผู้คนหลีกเลี่ยงสิ่งนี้โดยทำ:
foo(flag == TRUE);
เพื่อบังคับให้นิพจน์เป็นบูล C ++ แต่ถ้าคุณกำหนด # TRUE! FALSE คุณจะได้:
foo(flag == !0);
ซึ่งสิ้นสุดการทำการเปรียบเทียบแบบ int-to-bool ที่สามารถทริกเกอร์คำเตือนได้
หากคุณใช้ C99 คุณสามารถใช้_Bool
ประเภท ไม่#include
จำเป็น คุณไม่จำเป็นต้องรักษามันเช่นจำนวนเต็ม แต่ที่1
เป็นtrue
และ0
เป็นfalse
เป็น
จากนั้นคุณสามารถกำหนดและTRUE
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>
และการใช้งานbool
, true
และfalse
เช่นมาตรฐานต้องการให้คุณ
ปัจจุบันC99สนับสนุนชนิดบูลีน #include <stdbool.h>
แต่คุณจำเป็นต้อง
ตัวอย่าง:
#include <stdbool.h>
int main()
{
bool arr[2] = {true, false};
printf("%d\n", arr[0] && arr[1]);
printf("%d\n", arr[0] || arr[1]);
return 0;
}
เอาท์พุท:
0
1
นี่คือสิ่งที่ฉันใช้:
enum {false, true};
typedef _Bool bool;
_Bool
เป็นชนิดในตัวใน C. มันมีไว้สำหรับค่าบูลีน
คุณสามารถใช้#define
คำสั่งดังต่อไปนี้:
#define TRUE 1
#define FALSE 0
#define NOT(arg) (arg == TRUE)? FALSE : TRUE
typedef int bool;
และใช้ดังนี้:
bool isVisible = FALSE;
bool isWorking = TRUE;
isVisible = NOT(isVisible);
และอื่น ๆ
arg
และนิพจน์โดยรวม: #define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE)
. อย่างไรก็ตามจะเป็นการดีกว่าที่จะทดสอบความผิดพลาด (จะให้คำตอบที่ถูกต้องแม้ว่าจะarg
เป็น 23 แทนที่จะเป็น 0 หรือ 1: #define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE)
แต่แน่นอนว่าการแสดงออกทั้งหมดสามารถลดลงได้#define NOT(arg) (!(arg))
ซึ่งแน่นอนว่าผลลัพธ์เดียวกัน