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:
ฉันแก่พอที่ฉันจะใช้ints ธรรมดาเป็นประเภทบูลของฉันโดยไม่มีการพิมพ์หรือกำหนดหรือ 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และถูกประกาศในfalseenum
สิ่งที่อันตรายยิ่งกว่านั้นก็คือการประกาศ
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มาโคร (และว่าได้รับอนุญาตอย่างน้อยเป็นวัดคลองท่อม) แต่คุณไม่สามารถuntypedeftypedef แม้ว่ามันจะไม่เปลี่ยนแรงผลักดันหลักของความคิดเห็นแรกของคุณ
สิ่งใดที่ไม่ใช่ศูนย์จะถูกประเมินเป็นจริงในการดำเนินการบูลีนดังนั้นคุณสามารถทำได้
#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จะถูกแปลงเป็นเมื่อได้รับมอบหมายให้1x_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เป็น
จากนั้นคุณสามารถกำหนดและTRUEFALSE
_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))ซึ่งแน่นอนว่าผลลัพธ์เดียวกัน