ประเภทข้อมูล C
| ไลบรารีมาตรฐาน C (libc) |
|---|
| หัวข้อทั่วไป |
| ส่วนหัวเบ็ดเตล็ด |
ในภาษาการเขียนโปรแกรม C ชนิดข้อมูลประกอบด้วยความหมายและลักษณะเฉพาะของการจัดเก็บข้อมูล โดยจะแสดงออกมาในไวยากรณ์ของภาษาในรูปแบบของการประกาศตำแหน่งหน่วยความจำหรือตัวแปรชนิดข้อมูลยังเป็นตัวกำหนดประเภทของการดำเนินการหรือวิธีการประมวลผลข้อมูลอีกด้วย
ภาษา C มีประเภททางคณิตศาสตร์พื้นฐาน เช่น ประเภท จำนวนเต็มและจำนวนจริงและไวยากรณ์สำหรับสร้างอาร์เรย์และประเภทผสม ไลบรารีมาตรฐานของภาษา Cมีคำจำกัดความเพิ่มเติมของประเภทสนับสนุนที่มีคุณสมบัติเพิ่มเติม เช่น การจัดเก็บข้อมูลที่มีขนาดที่แน่นอน โดยไม่ขึ้นอยู่กับการใช้งานภาษาบนแพลตฟอร์มฮาร์ดแวร์เฉพาะ[ 1 ] [ 2 ]
ประเภทหลัก
ประเภทหลัก
ภาษา C มีตัวระบุชนิดข้อมูลทางคณิตศาสตร์พื้นฐานสี่แบบ ได้แก่char, int, floatและdouble(รวมถึงชนิดข้อมูลบูลีนด้วยbool) และตัวดัดแปลง ได้แก่signed, unsigned, short, และlongตารางต่อไปนี้แสดงรายการการผสมผสานที่อนุญาตในการระบุการประกาศเฉพาะขนาดพื้นที่จัดเก็บข้อมูลจำนวนมาก
| พิมพ์ | คำอธิบาย | ขนาด (บิต) [ a ] | ตัวระบุรูปแบบ | พิสัย | คำต่อท้ายสำหรับค่าคงที่ทศนิยม |
|---|---|---|---|---|---|
bool | ประเภท บูลีน เพิ่มในC23 (ก่อนหน้านี้_Boolเพิ่มในC99 [ 3 ]แต่ไม่ได้ระบุขนาดและช่วง) | 1 (ตรงเป๊ะ) | %d | [ เท็จ, จริง] | ไม่มีข้อมูล |
char | หน่วยที่เล็กที่สุดที่สามารถระบุตำแหน่งของเครื่องได้ซึ่งสามารถบรรจุชุดอักขระพื้นฐานได้ เป็น ประเภท จำนวนเต็มประเภทจริงอาจเป็นแบบมีเครื่องหมายหรือไม่มีเครื่องหมาย ประกอบด้วยCHAR_BITบิต[ 4 ] | ≥8 | %c | [ CHAR_MIN , CHAR_MAX ] | ไม่มีข้อมูล |
signed char | มีขนาดเท่ากับcharแต่รับประกันว่าจะมีการลงนาม สามารถบรรจุช่วง อย่างน้อย [ −127, +127 ] ได้ [ 4 ] [ b ] | ≥8 | %c[ค] | [ SCHAR_MIN , SCHAR_MAX ] [ 7 ] | ไม่มีข้อมูล |
unsigned char | มีขนาดเท่ากับcharแต่รับประกันว่าไม่มีเครื่องหมาย ประกอบด้วยช่วง อย่างน้อย [ 0, 255 ] [ 8 ] | ≥8 | %c[ d ] | [ 0, UCHAR_MAX ] | ไม่มีข้อมูล |
| ประเภทจำนวนเต็ม สั้นแบบมีเครื่องหมาย สามารถบรรจุได้อย่างน้อย[−32 767 ,+32 767 ]ช่วง [ 4 ] [ b ] | ≥16 | %hiหรือ%hd | [ SHRT_MIN , SHRT_MAX ] | ไม่มีข้อมูล |
| ชนิดข้อมูลจำนวนเต็ม สั้นที่ไม่มีเครื่องหมาย ประกอบด้วยอย่างน้อย[0 ,65 535 ]ช่วง [ 4 ] | ≥16 | %hu | [ 0, USHRT_MAX ] | ไม่มีข้อมูล |
| ประเภทจำนวนเต็มแบบมีเครื่องหมายพื้นฐาน สามารถเก็บค่าได้อย่างน้อย[−32 767 ,+32 767 ]ช่วง [ 4 ] [ b ] | ≥16 | %iหรือ%d | [ INT_MIN , INT_MAX ] | ไม่มี[ 9 ] |
| ชนิดข้อมูลจำนวนเต็มที่ไม่มีเครื่องหมายพื้นฐาน ประกอบด้วยอย่างน้อย[0 ,65 535 ]ช่วง [ 4 ] | ≥16 | %u | [ 0, UINT_MAX ] | uหรือU [ 9 ] |
| ประเภทจำนวนเต็มแบบมีเครื่องหมาย ยาวสามารถเก็บค่าได้อย่างน้อย[−2 147 483 647 ,+2 147 483 647 ]ช่วง [ 4 ] [ b ] | ≥32 | %liหรือ%ld | [ LONG_MIN , LONG_MAX ] | lหรือL [ 9 ] |
| ประเภทจำนวนเต็มไม่ติดลบ แบบยาวสามารถเก็บค่าได้อย่างน้อย[0 ,4 294 967 295 ]ช่วง [ 4 ] | ≥32 | %lu | [ 0, ULONG_MAX ] | ทั้งuหรือUและlหรือL [ 9 ] |
| ประเภทจำนวนเต็มแบบมีเครื่องหมาย ยาวมากสามารถเก็บค่าได้อย่างน้อย[−9 223 372 036 854 775 807 ,+9 223 372 036 854 775 807 ]ช่วง [ 4 ] [ b ]ระบุไว้ตั้งแต่มาตรฐานเวอร์ชัน C99 | ≥64 | %lliหรือ%lld | [ LLONG_MIN , LLONG_MAX ] | llหรือLL [ 9 ] |
| ประเภทจำนวนเต็ม ยาวมากที่ไม่มีเครื่องหมาย ประกอบด้วยอย่างน้อย[0 ,18 446 744 073 709 551 615 ]ช่วง [ 4 ]ระบุตั้งแต่มาตรฐานเวอร์ชัน C99 | ≥64 | %llu | [ 0, ULLONG_MAX ] | ทั้งuหรือUและllหรือLL [ 9 ] |
float | ประเภทเลขทศนิยมจริง มักเรียกว่าประเภทเลขทศนิยมความแม่นยำเดี่ยว คุณสมบัติที่แท้จริงไม่ได้ระบุไว้ (ยกเว้นขีดจำกัดขั้นต่ำ) อย่างไรก็ตาม ในระบบส่วนใหญ่ นี่คือรูปแบบเลขทศนิยมไบนารีความแม่นยำเดี่ยว IEEE 754 (32 บิต) รูปแบบนี้เป็นข้อกำหนดของภาคผนวก F ที่เป็นทางเลือก "การคำนวณเลขทศนิยม IEC 60559" | แปลงจากข้อความ: [ e ]
| เอฟหรือเอฟ | ||
double | ประเภทเลขทศนิยมจริง มักเรียกว่าประเภทเลขทศนิยมความแม่นยำสองเท่า คุณสมบัติที่แท้จริงไม่ได้ระบุไว้ (ยกเว้นขีดจำกัดขั้นต่ำ) อย่างไรก็ตาม ในระบบส่วนใหญ่ นี่คือรูปแบบเลขทศนิยมไบนารีความแม่นยำสองเท่า IEEE 754 (64 บิต) รูปแบบนี้เป็นข้อกำหนดของภาคผนวก F ที่เป็นทางเลือก "การคำนวณเลขทศนิยม IEC 60559" |
| ไม่มี | ||
long double | ชนิดข้อมูลทศนิยมจริง มักถูกแปลงเป็น รูปแบบตัวเลขทศนิยม ความแม่นยำสูงคุณสมบัติที่แท้จริงไม่ได้ระบุไว้ อาจเป็นรูปแบบทศนิยมความแม่นยำสูง x86 (80 บิต แต่โดยทั่วไปคือ 96 บิต หรือ 128 บิตในหน่วยความจำพร้อมไบต์เติม ) รูปแบบ " double-double " ที่ไม่ใช่มาตรฐาน IEEE (128 บิต) รูปแบบทศนิยมความแม่นยำสูง IEEE 754 (128 บิต) หรือเหมือนกับ double ดูบทความเกี่ยวกับ long doubleสำหรับรายละเอียดเพิ่มเติม | %Lf%LF%Lg%LG%Le%LE%La%LA[ f ] | ลหรือแอล |
- ↑คำศัพท์มาตรฐานที่ใช้เรียกขนาดของชนิดข้อมูลจำนวนเต็มในหน่วยบิตคือความกว้าง (width ) ความกว้างนี้ไม่รวมบิตที่ใช้เติมช่องว่าง (padding bits)
- 1 2 3 4 5ช่วงค่าต่ำสุด [ −(2 n −1 −1), 2 n −1 −1 ] (เช่น [−127,127]) มาจากการแสดงจำนวนเต็มแบบต่างๆ ที่มาตรฐานอนุญาต (ส่วนเติมเต็มหนึ่ง ,เครื่องหมาย-ขนาด ,ส่วนเติมเต็มสอง ) [ 5 ]อย่างไรก็ตาม แพลตฟอร์มส่วนใหญ่ใช้ส่วนเติมเต็มสอง ซึ่งหมายถึงช่วงค่าในรูปแบบ [ −2 m −1 , 2 m −1 −1 ]โดยที่ m ≥ nสำหรับการใช้งานเหล่านี้ เช่น [−128,127] (และ ) สำหรับ อักขระแบบมีเครื่องหมาย 8 บิตตั้งแต่ C23 การแสดงค่าที่อนุญาตเพียงอย่างเดียวคือส่วนเติมเต็มสอง ดังนั้นค่าจึงอยู่ในช่วงอย่างน้อย [ −2 n −1 , 2 n −1 −1 ] [ 6 ]
SCHAR_MIN == −128SCHAR_MAX == 127 - ↑หรือ
%hhiสำหรับการแสดงผลเชิงตัวเลข - ↑หรือ
%hhuสำหรับการแสดงผลเชิงตัวเลข - ↑สตริงรูปแบบเหล่านี้ยังมีอยู่สำหรับการจัดรูปแบบข้อความ แต่จะทำงานกับค่าทศนิยม
- 1 2ตัวพิมพ์ใหญ่แตกต่างจากตัวพิมพ์เล็กในผลลัพธ์ ตัวระบุตัวพิมพ์ใหญ่จะสร้างค่าเป็นตัวพิมพ์ใหญ่ และตัวระบุตัวพิมพ์เล็กจะสร้างค่าเป็นตัวพิมพ์เล็ก (%A, %E, %F, %G จะสร้างค่าเช่น INF, NAN และ E (เลขชี้กำลัง) ในตัวพิมพ์ใหญ่)
ขนาดจริงของ ชนิด ข้อมูลจำนวนเต็มจะแตกต่างกันไปตามการใช้งาน มาตรฐานกำหนดเพียงความสัมพันธ์ด้านขนาดระหว่างชนิดข้อมูลและขนาดขั้นต่ำสำหรับแต่ละชนิดข้อมูลเท่านั้น:
ข้อกำหนดความสัมพันธ์คือ ต้องlong longไม่น้อยกว่าlongซึ่งไม่น้อยกว่า ซึ่งไม่intน้อยกว่าshortเนื่องจากcharขนาดของ เป็นขนาดขั้นต่ำสุดของชนิดข้อมูลที่รองรับเสมอ จึงไม่มีชนิดข้อมูลอื่นใด (ยกเว้นบิตฟิลด์ ) ที่จะมีขนาดเล็กกว่าได้
ขนาดขั้นต่ำสำหรับcharคือ 8 บิต ขนาดขั้นต่ำสำหรับshortและintคือ 16 บิต ส่วน สำหรับlongนั้นมีขนาด 32 บิต และlong longต้องมีอย่างน้อย 64 บิต
ประเภทintควรเป็นประเภทจำนวนเต็มที่โปรเซสเซอร์เป้าหมายทำงานได้อย่างมีประสิทธิภาพมากที่สุด ซึ่งช่วยให้มีความยืดหยุ่นสูง เช่น ประเภททั้งหมดสามารถเป็น 64 บิตได้ อย่างไรก็ตาม รูปแบบความกว้างของจำนวนเต็ม (โมเดลข้อมูล) ที่แตกต่างกันหลายแบบก็เป็นที่นิยม เนื่องจากโมเดลข้อมูลกำหนดวิธีการสื่อสารระหว่างโปรแกรมต่างๆ จึงมีการใช้โมเดลข้อมูลที่เป็นเอกภาพภายในอินเทอร์เฟซแอปพลิเคชันระบบปฏิบัติการที่กำหนด[ 10 ]
ในทางปฏิบัติcharโดยทั่วไปจะมีขนาด 8 บิต และshortโดยทั่วไปจะมีขนาด 16 บิต (เช่นเดียวกับค่าที่ไม่ระบุเครื่องหมาย) สิ่งนี้เป็นจริงสำหรับแพลตฟอร์มที่หลากหลาย เช่นSunOS 4 Unix ในยุค 1990, Microsoft MS-DOS , Linuxรุ่นใหม่และ Microchip MCC18 สำหรับไมโครคอนโทรลเลอร์ PIC 8 บิตแบบฝังตัวPOSIX กำหนดให้มีcharขนาด 8 บิตพอดี[ 11 ] [ 12 ]
กฎต่างๆ ในมาตรฐาน C ทำให้unsigned charประเภทพื้นฐานที่ใช้สำหรับอาร์เรย์เหมาะสมที่จะจัดเก็บวัตถุที่ไม่ใช่ฟิลด์บิตใดๆ ได้แก่ การไม่มีบิตเติมและการแสดงกับดัก คำจำกัดความของการแสดงวัตถุ [ 8 ] และความเป็นไปได้ของ การใช้นามแฝง[ 13 ]
ขนาดและลักษณะการทำงานของชนิดข้อมูลจุดลอยตัวนั้นแตกต่างกันไปตามการใช้งาน ข้อกำหนดเพียงอย่างเดียวคือlong doubleต้องไม่น้อยกว่าdoubleซึ่งต้องไม่น้อยกว่า โดยปกติแล้ว จะใช้รูปแบบเลขฐานสองแบบIEEE 754floatขนาด 32 บิตและ 64 บิต สำหรับ และตามลำดับfloatdouble
มาตรฐานC99ประกอบด้วยชนิดข้อมูลจุดลอยตัวจริงแบบใหม่float_tและdouble_tซึ่งกำหนดไว้ใน ชนิดข้อมูล<math.h>เหล่านี้สอดคล้องกับชนิดข้อมูลที่ใช้สำหรับผลลัพธ์ระดับกลางของนิพจน์จุดลอยตัวเมื่อFLT_EVAL_METHODมีค่าเป็น 0, 1 หรือ 2 ชนิดข้อมูลเหล่านี้อาจมีความกว้างlong doubleมากกว่า
นอกจากนี้ C99 ยังเพิ่มประเภทข้อมูลที่ซับซ้อนได้แก่float _Complex, double _Complex, C11เพิ่ม ประเภท ข้อมูลสมมติ (ซึ่งอธิบายไว้ในภาคผนวกข้อมูลของ C99) ได้แก่, , การรวมส่วนหัวทำให้สามารถเข้าถึงประเภทข้อมูลเหล่านี้ได้โดยใช้และตามลำดับlong double _Complexfloat _Imaginarydouble _Imaginarylong double _Imaginary<complex.h>compleximaginary
ประเภทบูลีน
C99เพิ่มชนิดข้อมูลบูลีน (Boolean_Bool ) นอกจากนี้<stdbool.h>ส่วนหัวยังกำหนดให้boolเป็นชื่อเรียกย่อที่สะดวกสำหรับชนิดนี้ และยังมีมาโครสำหรับtrueและfalseอีก ด้วย _Boolทำงานคล้ายกับชนิดข้อมูลจำนวนเต็มปกติ โดยมีข้อยกเว้นหนึ่งอย่างคือ การแปลงใดๆ เป็น จะ_Boolให้ค่า 0 (เท็จ) ถ้าค่าเท่ากับ 0 มิฉะนั้นจะให้ค่า 1 (จริง) พฤติกรรมนี้มีไว้เพื่อหลีกเลี่ยงการโอเวอร์โฟลว์ของจำนวนเต็มในการแปลงแบบแคบโดยปริยาย ตัวอย่างเช่น ในโค้ดต่อไปนี้:
unsigned char b = 256 ;ถ้า( b ) { // ทำบางอย่าง}ตัวแปรbจะมีค่าเป็นเท็จหากunsigned charมีขนาด 8 บิต เนื่องจากค่า 256 ไม่สามารถใส่ลงในชนิดข้อมูลได้ ทำให้ใช้เพียง 8 บิตล่าง ส่งผลให้ได้ค่าเป็นศูนย์ อย่างไรก็ตาม การเปลี่ยนชนิดข้อมูลจะทำให้โค้ดก่อนหน้านี้ทำงานได้ตามปกติ
_Bool b = 256 ;ถ้า( b ) { // ทำบางอย่าง}ชนิดข้อมูลนี้_Boolยังช่วยให้ค่าที่เป็นจริงเปรียบเทียบกันได้เท่ากันเสมอ:
_Bool a = 1 ; _Bool b = 2 ;ถ้า( a == b ) { // โค้ดส่วนนี้จะทำงาน}ในC23 ( boolและค่าของมันtrueและfalse) กลายเป็นฟังก์ชันหลักของภาษา (ทำให้เนื้อหาของ<stdbool.h>ล้าสมัย[ 14 ] [ 15 ] ) ซึ่งช่วยให้สามารถใช้ตัวอย่างโค้ดต่อไปนี้ได้:
bool b = true ;ถ้า( b ) { // โค้ดนี้จะทำงาน}ประเภทจำนวนเต็มที่แม่นยำระดับบิต
ตั้งแต่C23เป็นต้นมา ภาษาอนุญาตให้โปรแกรมเมอร์กำหนดจำนวนเต็มที่มีความกว้างเป็นจำนวนบิตตามอำเภอใจ ประเภทเหล่านั้นระบุเป็น โดยที่Nเป็นนิพจน์ค่าคงที่จำนวนเต็มที่แสดงจำนวนบิต รวมถึงบิตเครื่องหมายสำหรับประเภทที่มีเครื่องหมาย ซึ่งแสดงในรูปแบบสองส่วนเติมเต็ม ค่าสูงสุดของNกำหนดโดยและมีค่าอย่างน้อยดังนั้น ประเภท(หรือ) จะมีค่าตั้งแต่ -2 ถึง 1 ในขณะที่จะมีค่าตั้งแต่ 0 ถึง 3 ประเภทยังมีอยู่ด้วย โดยมีค่าเป็น 0 หรือ 1 และไม่มีประเภทที่มีเครื่องหมายที่เทียบเท่ากัน[ 16 ]ข้อเสนอสำหรับC2Yเสนอให้ยกเลิกข้อจำกัดนี้และอนุญาตให้ซึ่งจะมีค่าที่เป็นไปได้คือ 0 และ -1 โดยลบกรณีพิเศษสำหรับออก[ 17 ]_BitInt(N)BITINT_MAXWIDTHULLONG_WIDTH_BitInt(2)signed_BitInt(2)unsigned_BitInt(2)unsigned_BitInt(1)signed_BitInt(1)unsigned_BitInt(1)
ขนาดและประเภทความแตกต่างของตัวชี้
ข้อกำหนดของภาษา C ประกอบด้วยtypedef s และเพื่อใช้แทนปริมาณที่เกี่ยวข้องกับหน่วยความจำ ขนาดของพวกมันถูกกำหนดตามความสามารถในการคำนวณทางคณิตศาสตร์ของโปรเซสเซอร์เป้าหมาย ไม่ใช่ความสามารถของหน่วยความจำ เช่น พื้นที่แอดเดรสที่ใช้งานได้ ทั้งสองประเภทนี้ถูกกำหนดไว้ในไฟล์เฮดเดอร์size_tptrdiff_t<stddef.h>
size_tเป็นชนิดข้อมูลจำนวนเต็มไม่ระบุเครื่องหมายที่ใช้แสดงขนาดของวัตถุใดๆ (รวมถึงอาร์เรย์) ในการใช้งานเฉพาะนั้นๆ ตัวดำเนินการ `sizeof` จะให้ค่าของชนิดข้อมูลนี้ขนาดสูงสุดของ `sizeof` กำหนดโดย`sizeof` ซึ่งเป็นค่าคงที่มาโครที่กำหนดไว้ในส่วนหัว ` sizeof` รับประกันว่า `sizeof` จะมีความกว้างอย่างน้อย 16 บิต นอกจากนี้ POSIX ยังรวมถึง `sizeof` ซึ่งเป็นชนิดข้อมูลจำนวนเต็มระบุเครื่องหมายที่มีความกว้างเท่ากับ `sizeof` ด้วยsize_tsize_tSIZE_MAX<stdint.h>size_tssize_tsize_t
ptrdiff_tเป็นชนิดข้อมูลจำนวนเต็มที่มีเครื่องหมาย ใช้สำหรับแสดงผลต่างระหว่างตัวชี้ รับประกันว่าจะมีผลเฉพาะกับตัวชี้ชนิดเดียวกันเท่านั้น การลบตัวชี้ที่มีชนิดข้อมูลต่างกันนั้นขึ้นอยู่กับการใช้งานของแต่ละระบบ
ส่วนติดต่อกับคุณสมบัติของประเภทพื้นฐาน
ข้อมูลเกี่ยวกับคุณสมบัติที่แท้จริง เช่น ขนาดของชนิดข้อมูลทางคณิตศาสตร์พื้นฐาน จะถูกระบุผ่านค่าคงที่มาโครในไฟล์เฮดเดอร์สองไฟล์: <limits.h>ไฟล์เฮดเดอร์หนึ่งกำหนดมาโครสำหรับชนิดข้อมูลจำนวนเต็ม และ<float.h>อีกไฟล์เฮดเดอร์หนึ่งกำหนดมาโครสำหรับชนิดข้อมูลทศนิยม ค่าที่แท้จริงจะขึ้นอยู่กับการใช้งานในแต่ละระบบ
คุณสมบัติของชนิดข้อมูลจำนวนเต็ม
CHAR_BIT– ขนาดของชนิดข้อมูล char ในหน่วยบิต ซึ่งโดยทั่วไปเรียกว่าขนาดของไบต์ (อย่างน้อย 8 บิต)SCHAR_MIN( C99) – ค่าต่ำสุดที่เป็นไปได้ของชนิดข้อมูลจำนวนเต็มที่มี เครื่องหมาย : signed char, signedSHRT_MINshort , signed int, signed long, signed long longINT_MINLONG_MINLLONG_MINSCHAR_MAX( C99) – ค่าสูงสุดที่เป็นไปได้ของชนิดข้อมูลจำนวนเต็มแบบมีเครื่องหมาย: signed char, signedSHRT_MAXshort , signed int, signed long, signed long longINT_MAXLONG_MAXLLONG_MAXUCHAR_MAX( C99)USHRT_MAX– ค่าสูงสุดที่เป็นไปได้ของชนิดข้อมูลจำนวนเต็มที่ไม่มี เครื่องหมาย : unsigned char, unsigned short, unsigned int,UINT_MAXunsigned long, unsigned long longULONG_MAXULLONG_MAXCHAR_MIN– ค่าต่ำสุดที่เป็นไปได้ของอักขระCHAR_MAX– ค่าสูงสุดที่เป็นไปได้ของอักขระMB_LEN_MAX– จำนวนไบต์สูงสุดในอักขระแบบหลายไบต์BOOL_WIDTH(C23) - ความกว้างบิตของ_Bool, เท่ากับ 1 เสมอCHAR_WIDTH(C23) - ความกว้างบิตของchar;CHAR_WIDTH,UCHAR_WIDTHและSCHAR_WIDTHมีค่าเท่ากันCHAR_BITตามนิยามSCHAR_WIDTH,SHRT_WIDTH,INT_WIDTH,LONG_WIDTH,LLONG_WIDTH(C23) - ความกว้างบิตของsigned char,short,int,long, และlong longตามลำดับUCHAR_WIDTH,USHRT_WIDTH,UINT_WIDTH,ULONG_WIDTH,ULLONG_WIDTH(C23) - ความกว้างบิตของunsigned char,unsigned short,unsigned int,unsigned long, และunsigned long longตามลำดับ
คุณสมบัติของชนิดข้อมูลจุดลอยตัว
FLT_MIN,DBL_MIN,LDBL_MIN– ค่าบวกขั้นต่ำที่ถูกทำให้เป็นมาตรฐานของ float, double และ long double ตามลำดับFLT_TRUE_MIN,DBL_TRUE_MIN,LDBL_TRUE_MIN(C11) – ค่าบวกต่ำสุดของ float, double และ long double ตามลำดับFLT_MAX,DBL_MAX,LDBL_MAX– ค่าสูงสุดที่จำกัดของ float, double และ long double ตามลำดับFLT_ROUNDS– โหมดการปัดเศษสำหรับการคำนวณเลขทศนิยมFLT_EVAL_METHOD(C99) – วิธีการประเมินนิพจน์ที่เกี่ยวข้องกับชนิดข้อมูลจุดลอยตัวที่แตกต่างกันFLT_RADIX– ฐานของเลขชี้กำลังในประเภทข้อมูลทศนิยมFLT_DIG,DBL_DIG,LDBL_DIG– number of decimal digits that can be represented without losing precision by float, double, long double, respectivelyFLT_EPSILON,DBL_EPSILON,LDBL_EPSILON– difference between 1.0 and the next representable value of float, double, long double, respectivelyFLT_MANT_DIG,DBL_MANT_DIG,LDBL_MANT_DIG– number ofFLT_RADIX-base digits in the floating-point significand for types float, double, long double, respectivelyFLT_MIN_EXP,DBL_MIN_EXP,LDBL_MIN_EXP– minimum negative integer such thatFLT_RADIXraised to a power one less than that number is a normalized float, double, long double, respectivelyFLT_MIN_10_EXP,DBL_MIN_10_EXP,LDBL_MIN_10_EXP– minimum negative integer such that 10 raised to that power is a normalized float, double, long double, respectivelyFLT_MAX_EXP,DBL_MAX_EXP,LDBL_MAX_EXP– maximum positive integer such thatFLT_RADIXraised to a power one less than that number is a normalized float, double, long double, respectivelyFLT_MAX_10_EXP,DBL_MAX_10_EXP,LDBL_MAX_10_EXP– maximum positive integer such that 10 raised to that power is a normalized float, double, long double, respectivelyDECIMAL_DIG(C99) – minimum number of decimal digits such that any number of the widest supported floating-point type can be represented in decimal with a precision ofDECIMAL_DIGdigits and read back in the original floating-point type without changing its value.DECIMAL_DIGis at least 10.
Fixed-width integer types
The C99 standard includes definitions of several new integer types to enhance the portability of programs.[2] The already available basic integer types were deemed insufficient, because their actual sizes are implementation defined and may vary across different systems. The new types are especially useful in embedded environments where hardware usually supports only several types and that support varies between different environments. All new types are defined in <inttypes.h> header and also are available at <stdint.h> header. The types can be grouped into the following categories:
- Exact-width integer types that are guaranteed to have the same number n of bits across all implementations. Included only if it is available in the implementation.
- Least-width integer types that are guaranteed to be the smallest type available in the implementation, that has at least specified number n of bits. Guaranteed to be specified for at least N=8,16,32,64.
- Fastest integer types that are guaranteed to be the fastest integer type available in the implementation, that has at least specified number n of bits. Guaranteed to be specified for at least N=8,16,32,64.
- Pointer integer types that are guaranteed to be able to hold a pointer. Included only if it is available in the implementation.
- ประเภทจำนวนเต็มที่มีความกว้างสูงสุด ซึ่งรับประกันได้ว่าเป็นประเภทจำนวนเต็มที่ใหญ่ที่สุดในระบบการใช้งาน
ตารางต่อไปนี้สรุปประเภทและอินเทอร์เฟซสำหรับรับรายละเอียดการใช้งาน ( nหมายถึงจำนวนบิต):
| ประเภทหมวดหมู่ | ประเภทลายเซ็น | ประเภทที่ไม่มีเครื่องหมาย | ||||
|---|---|---|---|---|---|---|
| พิมพ์ | ค่าต่ำสุด | ค่าสูงสุด | พิมพ์ | ค่าต่ำสุด | ค่าสูงสุด | |
| ความกว้างที่แน่นอน | intn_t | INTn_MIN | INTn_MAX | uintn_t | 0 | UINTn_MAX |
| ความกว้างน้อยที่สุด | int_leastn_t | INT_LEASTn_MIN | INT_LEASTn_MAX | uint_leastn_t | 0 | UINT_LEASTn_MAX |
| เร็วที่สุด | int_fastn_t | INT_FASTn_MIN | INT_FASTn_MAX | uint_fastn_t | 0 | UINT_FASTn_MAX |
| ตัวชี้ | intptr_t | INTPTR_MIN | INTPTR_MAX | uintptr_t | 0 | UINTPTR_MAX |
| ความกว้างสูงสุด | intmax_t | INTMAX_MIN | INTMAX_MAX | uintmax_t | 0 | UINTMAX_MAX |
ตัวกำหนดรูปแบบ printf และ scanf
ส่วนหัว นี้<inttypes.h>มีคุณสมบัติที่ช่วยเพิ่มประสิทธิภาพการทำงานของประเภทที่กำหนดไว้ใน<stdint.h>ส่วนหัว โดยจะกำหนดมาโครสำหรับ ตัวระบุ รูปแบบสตริง printfและscanfที่สอดคล้องกับประเภทที่กำหนดไว้<stdint.h>และฟังก์ชันต่างๆ สำหรับการทำงานกับ ประเภท intmax_tเหล่านั้นuintmax_tส่วนหัวนี้ถูกเพิ่มเข้ามาในC99
รูปแบบสตริงprintf
มาโครอยู่ในรูปแบบ`<fmt>` โดยที่`{fmt}`กำหนดรูปแบบการแสดงผล และเป็นหนึ่งใน`<decimal>`, `<hexadecimal>`, `<octal>`, `<unsigned>` และ`<integer>` ` {type}`กำหนดชนิดของอาร์กิวเมนต์ และเป็นหนึ่งใน`<int>` , ` <int>`, `<int>`, ` <int>`, `<int> `, โดยที่ `<int> ` สอดคล้องกับจำนวนบิตในอาร์กิวเมนต์PRI{fmt}{type}dxouinFASTnLEASTnPTRMAXn
สตริงรูปแบบscanf
มาโครอยู่ในรูปแบบ`<fmt>` โดยที่`{fmt}`กำหนดรูปแบบการแสดงผล และเป็นหนึ่งใน`<decimal>`, `<hexadecimal>`, `<octal>`, `<unsigned>` และ`<integer>` ` {type}`กำหนดชนิดของอาร์กิวเมนต์ และเป็นหนึ่งใน`<int>` , ` <int>`, `<int>`, ` <int>`, `<int> `, โดยที่ `<int> ` สอดคล้องกับจำนวนบิตในอาร์กิวเมนต์SCN{fmt}{type}dxouinFASTnLEASTnPTRMAXn
ฟังก์ชัน
ประเภทจุดลอยตัวเพิ่มเติม
เช่นเดียวกับชนิดข้อมูลจำนวนเต็มที่มีความกว้างคงที่ มาตรฐาน ISO/IEC TS 18661 กำหนดชนิดข้อมูลทศนิยมสำหรับการแลกเปลี่ยนข้อมูล IEEE 754 และรูปแบบขยายในระบบเลขฐานสองและฐานสิบ:
_FloatNสำหรับรูปแบบการแลกเปลี่ยนไบนารี_DecimalNสำหรับรูปแบบการแลกเปลี่ยนเลขฐานสิบ;_FloatNxสำหรับรูปแบบไบนารีแบบขยาย;_DecimalNxสำหรับรูปแบบเลขฐานสิบแบบขยาย
จุดชี้
ทุกชนิดข้อมูลTจะมีตัวชี้T ชนิดข้อมูลที่สอดคล้องกัน ตัวชี้คือชนิดข้อมูลที่เก็บที่อยู่ของตำแหน่งจัดเก็บข้อมูลของตัวแปรชนิดนั้นๆ โดยจะประกาศตัวชี้ด้วยเครื่องหมายดอกจัน (* *) ตามหลังชนิดข้อมูลพื้นฐานและอยู่หน้าชื่อตัวแปร การเว้นวรรคก่อนหรือหลังเครื่องหมายดอกจันนั้นไม่จำเป็น
char * p ; long * q ; int * r ;นอกจากนี้ เรายังสามารถประกาศพอยน์เตอร์สำหรับชนิดข้อมูลพอยน์เตอร์ได้ ซึ่งจะสร้างพอยน์เตอร์ทางอ้อมหลายตัว เช่นchar **และint ***รวมถึงพอยน์เตอร์ไปยังชนิดข้อมูลอาร์เรย์ด้วย ชนิดหลังนี้พบได้น้อยกว่าอาร์เรย์ของพอยน์เตอร์ และไวยากรณ์ของมันอาจทำให้สับสนได้:
char*pc[10];// array of 10 elements of 'pointer to char'char(*pa)[10];// pointer to a 10-element array of charThe element pc requires ten blocks of memory of the size of pointer-to-char (usually 40 or 80 bytes on common platforms), but element pa is only one pointer (size 4 or 8 bytes), and the data it refers to is an array of ten bytes (sizeof*pa==10).
C also has a "pointer-to-void", void *.[18] The name "pointer-to-void" does not imply it points to void memory (as void is an incomplete type with no size), but rather that it points to something of unspecified type. It must be converted to another pointer type before it can be dereferenced. A void * may not point to a function. A call to malloc returns void *, and free takes a void *.
C uses the concept of a null pointer to denote a pointer that does not refer to any valid data. The macro NULL is often used in place of a null pointer, relying on implicit type conversion when possible. However, this usage can be problematic and may be a source of programming errors. In particular, the expansion of NULL may have a pointer type or an integer type, depending on the implementation. C23 introduced the predefined constant nullptr and its type nullptr_t (which has the single value nullptr) to express a null pointer constant. nullptr is unambiguously a pointer, and may convert to any object or function pointer, and allows a specific nullptr_t case in _Generic.[19] The size and alignment of this type is the same as for a pointer to character type (or void *), but other pointer types may still have a different size and alignment; thus not all null pointers are replaceable with nullptr.[20]
Arrays
For every type T, except void and function types, there exist the types "array of N elements of type T". An array is a collection of values, all of the same type, stored contiguously in memory. An array of size N is indexed by integers from 0 up to and including N − 1. Here is a brief example:
inta[10];// array of 10 elements, each of type intอาร์เรย์สามารถกำหนดค่าเริ่มต้นได้ด้วยตัวกำหนดค่าเริ่มต้นแบบผสม แต่ไม่สามารถกำหนดค่าโดยตรงได้ อาร์เรย์จะถูกส่งไปยังฟังก์ชันโดยการส่งพอยเตอร์ไปยังองค์ประกอบแรก อาร์เรย์หลายมิติถูกกำหนดเป็น"อาร์เรย์ของอาร์เรย์..."และทุกมิติยกเว้นมิตินอกสุดจะต้องมีขนาดคงที่ในเวลาคอมไพล์
int aa [ 10 ][ 8 ]; // อาร์เรย์ที่มี 10 องค์ประกอบ แต่ละองค์ประกอบเป็นชนิด 'อาร์เรย์ขององค์ประกอบ int 8 ตัว'ในภาษา C สตริงมักถูกจัดเก็บเป็นอาร์เรย์ของchar( char[]) แต่สิ่งนี้แตกต่างจากพอยเตอร์ไปยังchar( char *) char[]ไม่สามารถกำหนดค่าใหม่ได้ และคงอยู่ที่ตำแหน่งที่ถูกกำหนด ในขณะที่char *สามารถกำหนดค่าใหม่ได้ แต่ไม่สามารถแก้ไขได้
char s [] = "Hello, world!" ; char * p = s ; // s สลายตัวเป็น &s[0], p ชี้ไปยังอักขระตัวแรกแม้ว่าฟังก์ชันจะรับค่าT[]เป็นพารามิเตอร์ แต่ฟังก์ชันนั้นจะสลายตัวเป็นT *ค่าที่ชี้ไปยังองค์ประกอบแรกของฟังก์ชันนั้น
void f ( int a []);// นี่เหมือนกับ: void f ( int * a );การกำหนดดัชนี ของอาร์เรย์นั้นกำหนดขึ้นตามเลขคณิตของตัวชี้นั่นa[i]คือ เทียบเท่ากับ[*(a + i) 21 ]
เอนัม
ในภาษา C นั้น enum เป็นชนิดจำนวนเต็มที่มีค่าจำกัดเฉพาะชุดของค่าคงที่ที่มีชื่อ[ 22 ]ไม่สามารถประกาศ enum ล่วงหน้าได้ นอกจากนี้ enum ยังสามารถกำหนดค่าโดยตรงได้ และมักใช้เพื่อswitchแจงนับกรณีต่างๆ หลายกรณี
#include <stddef.h>enum สถานะ{ OK = 200 , NOT_FOUND = 404 , SERVER_ERROR = 500 };const char * get_status_string ( enum Status status ) { switch ( status ) { case OK : return "สำเร็จ" ; case NOT_FOUND : return "ไม่พบ" ; case SERVER_ERROR : return "เกิดข้อผิดพลาดของเซิร์ฟเวอร์" ; default : unreachable (); } }ค่าคงที่ของ enum จะทราบได้ในระหว่างการคอมไพล์ และมักเป็นวิธีการกำหนดค่าคงที่จำนวนเต็มที่ปลอดภัยกว่าการใช้มาโคร ขนาดพื้นฐานของ enum โดยทั่วไปจะเป็นจำนวนเต็มintแต่ตั้งแต่ C23 เป็นต้นมา ขนาดพื้นฐานของ enum สามารถระบุได้โดยตรงให้เป็นชนิดข้อมูลจำนวนเต็มใดก็ได้
enum Color : char { RED = 1 , ORANGE , YELLOW , GREEN , BLUE , INDIGO , VIOLET };เนื่องจาก enum ไม่มีความปลอดภัยทางประเภท จึงสามารถกำหนดค่าให้กับ enum อื่นได้ นอกจากนี้ ค่าที่กำหนดให้กับ enum ไม่จำเป็นต้องอยู่ในช่วงค่าที่กำหนดไว้เสมอไป
enum Color color = YELLOW ; // YELLOW = 3 enum Month month = JUNE ; // JUNE = 6color = month ; // ตอนนี้สีคือ 6 (INDIGO) month = 999 ; // อาจไม่มีค่า 999 ใน enum Month แต่ก็ยังอนุญาตโครงสร้าง
โครงสร้าง (structs) รวบรวมการจัดเก็บข้อมูลหลายรายการ ซึ่งอาจมีชนิดข้อมูลแตกต่างกัน เข้าไว้ในบล็อกหน่วยความจำต่อเนื่องเพียงบล็อกเดียว โดยอ้างอิงด้วยตัวแปรเดียว สมาชิกอาจมีการเติมช่องว่างเพื่อการจัดเรียงหน่วยความจำดังนั้นจึงมักแนะนำให้เรียงลำดับฟิลด์จากขนาดใหญ่ที่สุดไปยังขนาดเล็กที่สุดเพื่อการใช้หน่วยความจำอย่างมีประสิทธิภาพ
struct Student { char name [ 50 ]; unsigned int id ; unsigned int semester ; float gpa ; };// การกำหนดค่าเริ่มต้นตามตำแหน่ง - ค่าจะตรงกับลำดับฟิลด์struct Student alice = { "Alice" , 123 , 2 , 3.8 }; // ตัวกำหนดค่าเริ่มต้นที่กำหนด (ตั้งแต่ C99) struct Student bob = { . name = "Bob" , . id = 246 , . semester = 1 , . gpa = 3.9 };โครงสร้างอาจใช้ฟิลด์บิตเพื่ออนุญาตให้ฟิลด์ต่างๆ ใช้หน่วยจัดเก็บข้อมูลร่วมกันได้ แต่รูปแบบการจัดวางนั้นขึ้นอยู่กับการใช้งานของแต่ละระบบ
struct Properties { // ฟิลด์สามฟิลด์สามารถบรรจุได้อย่างกะทัดรัดในหนึ่งไบต์unsigned char visible : 1 ; // a ใช้พื้นที่ 1 บิตunsigned char color : 3 ; // b ใช้พื้นที่ 3 บิตunsigned char size : 4 ; // c ใช้พื้นที่ 4 บิต};โครงสร้างหน่วยความจำของสตรัคเจอร์เป็นเรื่องของการใช้งานในแต่ละภาษาและแพลตฟอร์ม โดยมีข้อจำกัดบางประการ ที่อยู่หน่วยความจำของสมาชิกตัวแรกต้องเหมือนกับที่อยู่ของสตรัคเจอร์เอง สตรัคเจอร์สามารถเริ่มต้นหรือกำหนดค่าโดยใช้ลิเทอรัลแบบผสมได้ ฟังก์ชันอาจส่งคืนสตรัคเจอร์โดยตรง แม้ว่าโดยทั่วไปแล้วจะไม่ค่อยมีประสิทธิภาพในขณะรันไทม์ ตั้งแต่C99 เป็นต้น มา สตรัคเจอร์อาจลงท้ายด้วยสมาชิกอาร์เรย์ที่ยืดหยุ่นได้ด้วย
ฟังก์ชันอาจรับโครงสร้างข้อมูลเป็นพารามิเตอร์แบบส่งค่า แต่การทำเช่นนี้มีค่าใช้จ่ายสูงเนื่องจากต้องคัดลอกโครงสร้างข้อมูลทั้งหมด ในขณะเดียวกัน การส่งผ่านโดยใช้ตัวชี้มักจะเหมาะสมกว่า เนื่องจากทราบขนาดของตัวชี้ (โดยทั่วไปคือ 4 หรือ 8 ไบต์)
#include <stdio.h>// การส่งค่าแบบ pass by value void print_student ( struct Student s ) { printf ( "Name: %s, ID: %d, in semester %d, with GPA: %.2f \n " , s . name , s . id , s . semester , s . gpa ); }// การส่งผ่านด้วยพอยเตอร์void print_student ( struct Student * s ) { printf ( "ชื่อ: %s, รหัสประจำตัว: %d, ภาคการศึกษา %d, เกรดเฉลี่ย: %.2f \n " , s -> name , s -> id , s -> semester , s -> gpa ); }โครงสร้างสามารถประกอบขึ้นจากโครงสร้างอื่นๆ ได้:
struct Date { int year ; int month ; int day ; };struct Birthday { char name [ 50 ]; struct Date dob ; };โครงสร้างข้อมูลที่มีตัวชี้ไปยังโครงสร้างข้อมูลประเภทเดียวกัน มักใช้ในการสร้างโครงสร้างข้อมูลแบบเชื่อมโยง :
struct LinkedList { void * item ; // เก็บรายการปัจจุบันstruct LinkedList * next ; // เก็บรายการถัดไป หรือ NULL ถ้าไม่มีอะไรถัดไป};สหภาพแรงงาน
ประเภทแบบยูเนียน (Union type)เป็นโครงสร้างพิเศษที่อนุญาตให้เข้าถึงบล็อกหน่วยความจำเดียวกันได้โดยการเลือกใช้คำอธิบายประเภทที่แตกต่างกัน
// เก็บค่าจำนวนเต็มหรือค่าทศนิยมunion Number { int i ; float f ; } d ;d.i = 10 ; // ตอนนี้ d เก็บค่า 10 d.f = 3.14f ; // ตอน นี้ d เก็บค่า 3.14 ซึ่ง เขียนทับ ค่า10ในตัวอย่างต่อไปนี้ อาจมีการประกาศการรวมประเภทข้อมูลเพื่อให้สามารถอ่านข้อมูลเดียวกันได้ไม่ว่าจะเป็นจำนวนเต็ม ทศนิยม หรือประเภทอื่นๆ ที่ผู้ใช้กำหนด:
ยูเนียน{ int i ; float f ; struct { unsigned int u ; double d ; } s ; } u ;ขนาดโดยรวมของuคือขนาดของu.sซึ่งก็คือผลรวมของขนาดของu.s.uและu.s.dเนื่องจากsมีขนาดใหญ่กว่าทั้งiและfเมื่อกำหนดค่าให้กับu.iบางส่วนของu.fอาจยังคงอยู่หาก มีขนาด เล็กu.iกว่าu.f
การอ่านข้อมูลจากสมาชิกสหภาพแรงงานไม่เหมือนกับการหล่อหลอม เพราะคุณค่าของสมาชิกไม่ได้ถูกแปลง แต่เป็นการอ่านข้อมูลเท่านั้น
ตัวชี้ฟังก์ชัน
ตัวชี้ฟังก์ชันช่วยให้สามารถอ้างอิงถึงฟังก์ชันที่มีรูปแบบเฉพาะได้ ตัวอย่างเช่น เพื่อเก็บที่อยู่ของฟังก์ชันมาตรฐานไว้absในตัวแปรmy_int_f:
int ( * my_int_f )( int ) = & abs ; // สามารถละเว้นตัวดำเนินการ & ได้ แต่จะทำให้ชัดเจนว่ามีการใช้ "ที่อยู่ของ" abs ที่นี่ตัวชี้ฟังก์ชันจะถูกเรียกใช้โดยใช้ชื่อเช่นเดียวกับการเรียกใช้ฟังก์ชันทั่วไป
#include <stdio.h> #include <stdlib.h>int ( * my_abs )( int ) = & abs ; int x = -42 ; int abs_of_x = my_abs ( x ); printf ( "abs(%d) = %d \n " , x , abs_of_x );ตัวกำหนดประเภท
ประเภทต่างๆ ที่กล่าวมาข้างต้นสามารถจำแนกเพิ่มเติมได้ด้วยตัวกำหนดคุณสมบัติของประเภททำให้ได้ประเภทที่มีคุณสมบัติเฉพาะ ( ณ ปี 2014)และในC11นั้น มีตัวกำหนดคุณสมบัติประเภท (type qualifiers) สี่แบบในมาตรฐาน C:
const( C89 )volatile( C89 )restrict( ซี99 )_Atomic( C11 ) –ชื่อหลังมีชื่อส่วนตัวเพื่อหลีกเลี่ยงการขัดแย้งกับชื่อผู้ใช้[ 23 ] แต่ สามารถใช้ชื่อทั่วไป ได้หาก มีการรวมส่วนหัวไว้ด้วยatomic<stdatomic.h>
ในconstบรรดาตัวเลือกเหล่านี้ `const` เป็นที่รู้จักและใช้งานมากที่สุดโดยปรากฏอยู่ในไลบรารีมาตรฐานของภาษา Cและพบได้ในการใช้งานภาษา C ที่สำคัญใดๆ ซึ่งต้องเป็นไปตามหลักความถูกต้องของ `const` ส่วนตัว กำหนดคุณสมบัติอื่นๆ ส่วนใหญ่ใช้สำหรับการเขียนโปรแกรมระดับต่ำ: `const` มีจุดประสงค์เพื่อระงับการเพิ่มประสิทธิภาพของคอมไพเลอร์บนตัวแปรโดยแนะนำว่าตัวแปรอาจเปลี่ยนแปลงได้ตลอดเวลา `const` บ่งชี้ว่าวัตถุที่ชี้โดยตัวชี้จะถูกเข้าถึงโดยตัวชี้เองเท่านั้น และ ` const` บ่งชี้ว่าวัตถุนั้นเป็น "อะตอมิก" กล่าวคือ การอ่านและการเขียนไม่สามารถแบ่งแยกได้volatilerestrict_Atomic