คำตอบ:
วิธีการนี้จะใช้boolean
ประเภทจริง(และแก้ไขให้true
และfalse
) หากคอมไพเลอร์สนับสนุน (โดยเฉพาะ C ++)
อย่างไรก็ตามจะเป็นการดีกว่าถ้าตรวจสอบว่ามีการใช้งาน C ++ (ผ่านทาง__cplusplus
มาโคร) และใช้งานจริงtrue
หรือfalse
ไม่
ในคอมไพเลอร์ C, นี้จะเทียบเท่ากับและ0
(โปรดทราบว่าการลบวงเล็บจะทำให้เกิดความเสียหายเนื่องจากคำสั่งของการดำเนินการ)1
boolean
ประเภทนี้?
true
false
#define TRUE true
และ#define FALSE false
เมื่อใดก็ตามที่__cplusplus
มีการกำหนดไว้
คำตอบคือพกพาได้ ค่าตัวเลขของTRUE
และFALSE
ไม่สำคัญ อะไรคือสิ่งที่สำคัญก็คือว่าคำสั่งเช่นif (1 < 2)
ประเมินif (TRUE)
และงบเหมือนif (1 > 2)
ประเมินif (FALSE)
ประเมิน
ได้รับใน C (1 < 2)
ประเมิน1
และ(1 > 2)
ประเมิน0
ดังนั้นอย่างที่คนอื่นพูดไม่มีความแตกต่างในทางปฏิบัติเท่าที่เกี่ยวข้องกับคอมไพเลอร์ แต่โดยการให้คอมไพเลอร์กำหนดTRUE
และFALSE
ตามกฎของตัวเองคุณกำลังทำให้ความหมายชัดเจนสำหรับโปรแกรมเมอร์และคุณรับประกันความมั่นคงภายในโปรแกรมของคุณและไลบรารี่อื่น ๆ (สมมติว่าไลบรารี่อื่นนั้นเป็นไปตามมาตรฐาน C ... ประหลาดใจ)
บางประวัติ
พื้นฐานบางอย่างที่กำหนดไว้FALSE
เป็น0
และเป็นTRUE
-1
เช่นเดียวกับภาษาที่ทันสมัยมากพวกเขาตีความคุ้มค่าที่ไม่ใช่ศูนย์ใด ๆ ที่เป็นTRUE
แต่พวกเขาประเมิน-1
นิพจน์บูลีนที่มีความเป็นจริง NOT
การดำเนินการของพวกเขาถูกนำไปใช้โดยการเพิ่ม 1 และพลิกสัญญาณเพราะมันมีประสิทธิภาพในการทำเช่นนั้น ดังนั้น 'ไม่ X' -(x+1)
กลายเป็น ผลข้างเคียงของสิ่งนี้คือค่าที่5
ประเมินได้TRUE
แต่NOT 5
ประเมิน-6
ซึ่งก็เป็นเช่นกันTRUE
! การค้นหาข้อผิดพลาดประเภทนี้ไม่สนุก
ปฏิบัติที่ดีที่สุด
ได้รับการพฤตินัยกฎที่ศูนย์จะถูกตีความว่าเป็นFALSE
และใด ๆที่ไม่ใช่ศูนย์ค่าถูกตีความว่าเป็นTRUE
คุณควรไม่เคยเปรียบเทียบบูลกำลังมองหาการแสดงออกไปTRUE
FALSE
หรือ ตัวอย่าง:
if (thisValue == FALSE) // Don't do this!
if (thatValue == TRUE) // Or this!
if (otherValue != TRUE) // Whatever you do, don't do this!
ทำไม? เพราะโปรแกรมเมอร์หลายคนใช้ช็อตคัตในการรักษาint
s เป็นbool
s พวกเขาไม่เหมือนกัน แต่โดยทั่วไปคอมไพเลอร์อนุญาต ตัวอย่างเช่นมันถูกกฎหมายอย่างสมบูรณ์แบบที่จะเขียน
if (strcmp(yourString, myString) == TRUE) // Wrong!!!
นั่นดูถูกต้องและคอมไพเลอร์จะยอมรับมันอย่างมีความสุข แต่มันอาจจะไม่ทำในสิ่งที่คุณต้องการ นั่นเป็นเพราะค่าส่งคืนของstrcmp()
คือ
0 ถ้าyourString == myString
<0 ถ้าyourString < myString
> 0 ถ้าyourString > myString
ดังนั้นบรรทัดข้างต้นจะส่งกลับTRUE
เฉพาะเมื่อyourString > myString
เฉพาะเมื่อ
วิธีที่ถูกต้องในการทำเช่นนี้คือ
// Valid, but still treats int as bool.
if (strcmp(yourString, myString))
หรือ
// Better: lingustically clear, compiler will optimize.
if (strcmp(yourString, myString) != 0)
ในทำนองเดียวกัน:
if (someBoolValue == FALSE) // Redundant.
if (!someBoolValue) // Better.
return (x > 0) ? TRUE : FALSE; // You're fired.
return (x > 0); // Simpler, clearer, correct.
if (ptr == NULL) // Perfect: compares pointers.
if (!ptr) // Sleazy, but short and valid.
if (ptr == FALSE) // Whatisthisidonteven.
คุณมักจะพบ "ตัวอย่างที่ไม่ดี" เหล่านี้ในรหัสการผลิตและโปรแกรมเมอร์ที่มีประสบการณ์หลายคนสาบานกับพวกเขาพวกเขาทำงานบางตัวจะสั้นกว่าตัวเลือกที่ถูกต้อง (อวดรู้?) แต่ให้พิจารณา: เวอร์ชัน "ถูกต้อง" นั้นไม่มีประสิทธิภาพไม่น้อยกว่าพวกมันรับประกันว่าจะพกพาได้พวกมันจะผ่านแม้แต่ linters ที่เข้มงวดที่สุดและแม้แต่โปรแกรมเมอร์ใหม่ก็จะเข้าใจพวกมัน
มันไม่คุ้มค่าใช่มั้ย
(1==1)
1
ไม่มีแบบพกพามากกว่า กฎของคอมไพเลอร์คือกฎของภาษา C ซึ่งมีความชัดเจนและไม่น่าสงสัยเกี่ยวกับความหมายของความเท่าเทียมกันและตัวดำเนินการสัมพันธ์ ผมไม่เคยเห็นคอมไพเลอร์จะได้รับสิ่งนี้ไม่ถูกต้อง
strcmp
นั้นน้อยกว่าค่าที่เท่ากันหรือมากกว่านั้น 0 ไม่รับประกันว่าจะเป็น -1, 0 หรือ 1 และมีแพลตฟอร์มในรูปแบบที่ไม่คืนค่าเหล่านั้นเพื่อให้ได้ความเร็วในการใช้งาน ดังนั้นหากเป็นเช่นstrcmp(a, b) == TRUE
นั้นa > b
แต่ความหมายกลับกันอาจไม่เกิดขึ้น
(1==1)
และ1
เป็นทั้งประเภทคงที่ของการแสดงออกที่int
มีค่า 1 พวกเขาจะเหมือนกันมีความหมาย ฉันคิดว่าคุณสามารถเขียนโค้ดที่เหมาะสำหรับผู้อ่านที่ไม่ทราบ แต่ท้ายที่สุดแล้วมันจะจบที่ไหน?
(1 == 1)
เคล็ดลับจะเป็นประโยชน์สำหรับการกำหนดTRUE
ในลักษณะที่มีความโปร่งใสกับ C ที่ยังให้การพิมพ์ที่ดีกว่าใน C ++ รหัสเดียวกันสามารถตีความได้ว่าเป็น C หรือ C ++ หากคุณกำลังเขียนในภาษาที่เรียกว่า "Clean C" (ซึ่งคอมไพล์เป็น C หรือ C ++) หรือถ้าคุณกำลังเขียนไฟล์ส่วนหัวของ API ที่สามารถใช้โดยโปรแกรมเมอร์ C หรือ C ++
ใน C หน่วยแปล1 == 1
มีตรงความหมายเหมือนกัน1
; และมีความหมายเหมือนกัน1 == 0
0
อย่างไรก็ตามใน c ++ หน่วยแปลมีประเภท1 == 1
bool
ดังนั้นTRUE
มาโครนิยามวิธีดังกล่าวจึงรวมเข้ากับ C ++ ได้ดีขึ้น
ตัวอย่างของวิธีการที่จะบูรณาการที่ดีขึ้นเป็นที่สำหรับฟังก์ชั่นเช่นถ้าfoo
มีเกินสำหรับint
และbool
จากนั้นfoo(TRUE)
จะเลือกbool
เกินพิกัด หากTRUE
มีการกำหนดเช่นเดียว1
แล้วมันจะไม่ทำงานอย่างใน C ++ foo(TRUE)
จะต้องการint
เกินพิกัด
แน่นอน C99 แนะนำbool
, true
และfalse
และเหล่านี้สามารถนำมาใช้ในส่วนหัวของไฟล์ที่ทำงานร่วมกับ C99 และซี
อย่างไรก็ตาม:
TRUE
และFALSE
เป็น(0==0)
และ(1==0)
ถือกำเนิด C99หากคุณกำลังทำงานใน C ผสมและโครงการ c ++ และไม่ต้องการ C99 กำหนดกรณีที่ต่ำกว่าtrue
, false
และbool
แทน
#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif
ที่ถูกกล่าวว่า0==0
เคล็ดลับคือ (is?) ใช้โดยโปรแกรมเมอร์บางคนแม้ในรหัสที่ไม่เคยตั้งใจที่จะทำงานร่วมกับ C ++ ในทางใดทางหนึ่ง นั่นไม่ได้ซื้ออะไรเลยและแนะนำว่าโปรแกรมเมอร์มีความเข้าใจผิดเกี่ยวกับการทำงานของบูลีนในซี
ในกรณีที่คำอธิบาย C ++ ไม่ชัดเจนนี่คือโปรแกรมทดสอบ:
#include <cstdio>
void foo(bool x)
{
std::puts("bool");
}
void foo(int x)
{
std::puts("int");
}
int main()
{
foo(1 == 1);
foo(1);
return 0;
}
ผลลัพธ์:
bool
int
สำหรับคำถามจากความคิดเห็นว่าฟังก์ชัน C ++ มากเกินไปเกี่ยวข้องกับการเขียนโปรแกรม C และ C ++ แบบผสมอย่างไร สิ่งเหล่านี้แสดงให้เห็นถึงความแตกต่างของประเภท เหตุผลที่ถูกต้องสำหรับการต้องการtrue
ค่าคงที่ที่จะbool
รวบรวมเมื่อ C ++ สำหรับการวินิจฉัยที่สะอาด ที่ระดับการเตือนสูงสุดคอมไพเลอร์ C ++ อาจเตือนเราเกี่ยวกับการแปลงถ้าเราผ่านจำนวนเต็มเป็นbool
พารามิเตอร์ เหตุผลหนึ่งในการเขียนใน Clean C ไม่เพียง แต่รหัสของเราจะพกพาได้มากกว่า (เพราะคอมไพเลอร์ของ C ++ ไม่เพียง แต่คอมไพเลอร์ C เท่านั้น) แต่เราสามารถได้รับประโยชน์จากความคิดเห็นการวินิจฉัยของคอมไพเลอร์ C ++
TRUE
นั้นจะแตกต่างกันภายใต้ C ++
#ifdef __cplusplus
เพื่อแสดงเจตนาของคุณได้ชัดเจนยิ่งขึ้น
bool
และint
ไม่เรื่องมากในทางปฏิบัติเนื่องจากพวกเขาเป็นโดยปริยายแปลงสภาพให้แก่กันและกัน (และในCจริง"เดียวกัน"ทราบคำพูด แม้ว่า) และมีสถานการณ์ไม่มากนักที่คุณจำเป็นต้องแยกแยะระหว่างสองสถานการณ์นี้ "ไม่มาก"อาจจะหนักเกินไป"น้อยกว่าเมื่อเปรียบเทียบกับรหัสที่ใช้แม่แบบและการใช้งานมากเกินไป"อาจจะดีกว่านี้
#define TRUE (1==1)
#define FALSE (!TRUE)
เทียบเท่ากับ
#define TRUE 1
#define FALSE 0
ในซี
ผลมาจากผู้ประกอบการเชิงสัมพันธ์เป็นหรือ0
รับประกันได้ว่าจะได้รับการประเมินไปและมีการประกันเพื่อรับการประเมินเพื่อ1
1==1
1
!(1==1)
0
ไม่มีเหตุผลใดที่จะใช้แบบฟอร์มแรก โปรดทราบว่ารูปแบบแรกนั้นไม่ได้มีประสิทธิภาพน้อยกว่าเมื่อใช้กับคอมไพเลอร์เกือบทั้งหมดนิพจน์คงที่จะถูกประเมินที่เวลาคอมไพล์แทนที่จะเป็นเวลารันไทม์ สิ่งนี้ได้รับอนุญาตตามกฎนี้:
(C99, 6.6p2) "นิพจน์คงที่สามารถประเมินได้ระหว่างการแปลมากกว่ารันไทม์และอาจถูกนำไปใช้ในสถานที่ใด ๆ ที่อาจมีค่าคงที่"
PC-Lint จะออกข้อความ (506 บูลีนค่าคงที่) หากคุณไม่ได้ใช้ตัวอักษรTRUE
และFALSE
มาโคร:
สำหรับ C, ควรได้รับการกำหนดให้เป็น
TRUE
1
อย่างไรก็ตามภาษาอื่น ๆ ใช้ปริมาณที่มากกว่า 1 ดังนั้นโปรแกรมเมอร์บางคนรู้สึกว่า!0
มันปลอดภัย
นอกจากนี้ใน C99 stdbool.h
คำจำกัดความของมาโครบูลีนtrue
และfalse
ใช้ตัวอักษรโดยตรง:
#define true 1
#define false 0
1==1
รับประกันว่าจะได้รับการประเมินเพื่อ1
if(foo == true)
ซึ่งจะเปลี่ยนจากการปฏิบัติที่ไม่ดีไปจนถึงรถบั๊กแบน
(x == TRUE)
x
นอกเหนือจาก C ++ (กล่าวถึงแล้ว) ประโยชน์อีกอย่างหนึ่งก็คือเครื่องมือวิเคราะห์แบบคงที่ คอมไพเลอร์จะทำไปกับความไร้ประสิทธิภาพใด ๆ แต่ตัววิเคราะห์แบบคงที่สามารถใช้ประเภทนามธรรมของตัวเองเพื่อแยกความแตกต่างระหว่างผลการเปรียบเทียบและประเภทจำนวนเต็มอื่น ๆ ดังนั้นจึงรู้โดยปริยายว่า TRUE ต้องเป็นผลของการเปรียบเทียบและไม่ควรสันนิษฐานว่า ด้วยจำนวนเต็ม
เห็นได้ชัดว่า C บอกว่าพวกเขาเข้ากันได้ แต่คุณอาจเลือกที่จะห้ามการใช้คุณสมบัตินั้นโดยเจตนาเพื่อช่วยไฮไลต์ข้อบกพร่อง - ตัวอย่างเช่นที่บางคนอาจสับสน&
และ&&
หรือพวกเขาทำผิดพลาดต่อหน้าผู้ให้บริการ
if (boolean_var == TRUE)
โดยวิธีการของการขยายตัวif (boolean_var == (1 == 1))
ซึ่งต้องขอบคุณข้อมูลประเภทที่เพิ่มขึ้นของโหนดตกอยู่ในรูปแบบ(1 == 1)
if (<*> == <boolean_expr>)
ความแตกต่างที่เป็นจริงคืออะไร 0
ได้รับการประเมินไปfalse
และได้รับการประเมินเพื่อ1
true
ความจริงที่ว่าคุณใช้นิพจน์บูลีน ( 1 == 1
) หรือ1
เพื่อกำหนดtrue
ไม่สร้างความแตกต่างใด ๆ int
พวกเขาทั้งสองได้รับการประเมินเพื่อ
ขอให้สังเกตว่าstdbool.h
ไลบรารี่มาตรฐาน C นั้นมีหัวข้อเฉพาะสำหรับการกำหนดบูลีน:
true
ได้รับการประเมินไป1
และได้รับการประเมินเพื่อfalse
0
C ไม่ทราบเกี่ยวกับประเภทบูลพื้นเมืองพวกเขากำลังเพียง ints
int
ที่มีค่าหรือ0
1
C มีประเภทบูลีนจริง ( _Bool
โดยมีแมโครbool
กำหนดไว้<stdbool.h>
แต่ถูกเพิ่มใน C99 เท่านั้นซึ่งไม่ได้เปลี่ยนซีแมนทิกส์ของโอเปอเรเตอร์เพื่อใช้ชนิดใหม่
_Bool
และมี<stdbool.h>
#define bool _Bool
1 == 1
int
แก้ไข
เราไม่ทราบค่าที่แน่นอนว่า TRUE เท่ากับและคอมไพเลอร์สามารถมีคำจำกัดความของตัวเอง ดังนั้นสิ่งที่คุณทำคือการใช้คอมไพเลอร์ภายในสำหรับคำจำกัดความ สิ่งนี้ไม่จำเป็นเสมอไปถ้าคุณมีนิสัยการเขียนโปรแกรมที่ดี แต่สามารถหลีกเลี่ยงปัญหาสำหรับรูปแบบการเข้ารหัสที่ไม่ดีเช่น:
ถ้า ((a> b) == TRUE)
นี่อาจเป็นหายนะหากคุณกำหนด TRUE ด้วยตนเองเป็น 1 ในขณะที่ค่าภายในของ TRUE เป็นอีกหนึ่งค่า
>
ดำเนินการให้ผลตอบแทน 1 เสมอสำหรับจริง 0 สำหรับเท็จ ไม่มีความเป็นไปได้ที่คอมไพเลอร์ C จะได้รับสิ่งนี้ผิด การเปรียบเทียบความเท่าเทียมกันTRUE
และFALSE
สไตล์ที่ไม่ดี if (a > b)
ดังกล่าวข้างต้นเป็นลายลักษณ์อักษรอย่างชัดเจนมากขึ้นเป็น แต่ความคิดที่ว่าคอมไพเลอร์ C ที่แตกต่างกันสามารถปฏิบัติต่อความจริงและเท็จต่างกันเพียงแค่ไม่ถูกต้อง
โดยทั่วไปในภาษาการเขียนโปรแกรม C จะมีการกำหนด 1 เป็นจริงและ 0 ถูกกำหนดเป็นเท็จ ดังนั้นทำไมคุณเห็นดังต่อไปนี้ค่อนข้างบ่อย:
#define TRUE 1
#define FALSE 0
อย่างไรก็ตามตัวเลขใด ๆ ที่ไม่เท่ากับ 0 จะถูกประเมินเป็นจริงเช่นกันในคำสั่งแบบมีเงื่อนไข ดังนั้นโดยใช้ด้านล่าง:
#define TRUE (1==1)
#define FALSE (!TRUE)
คุณสามารถแสดงให้เห็นอย่างชัดเจนว่าคุณพยายามที่จะเล่นอย่างปลอดภัยโดยการทำผิดพลาดเท่ากับสิ่งที่ไม่เป็นความจริง
#define TRUE (’/’/’/’)
;#define FALSE (’-’-’-’)
(นำมาจากcoding-guidelines.com/cbook/cbook1_1.pdfหน้า 871)