ดูเหมือนว่าเป็นคำถามง่าย ๆ แต่ฉันไม่พบด้วยการค้นหา Stack Overflow หรือ Google ประเภทใดตามด้วย_t
ค่าเฉลี่ย เช่น
int_t anInt;
ฉันเห็นรหัส C จำนวนมากเพื่อจัดการกับฮาร์ดแวร์อย่างใกล้ชิดฉันอดไม่ได้ที่จะคิดว่ามันเกี่ยวข้องกัน
ดูเหมือนว่าเป็นคำถามง่าย ๆ แต่ฉันไม่พบด้วยการค้นหา Stack Overflow หรือ Google ประเภทใดตามด้วย_t
ค่าเฉลี่ย เช่น
int_t anInt;
ฉันเห็นรหัส C จำนวนมากเพื่อจัดการกับฮาร์ดแวร์อย่างใกล้ชิดฉันอดไม่ได้ที่จะคิดว่ามันเกี่ยวข้องกัน
คำตอบ:
อย่างที่ทราบกันแล้วว่าดักลาส Mayle มันเป็นชื่อประเภท ดังนั้นคุณจะไม่ควรปิดท้ายชื่อตัวแปรหรือชื่อฟังก์ชั่นด้วย ' _t
' เพราะอาจทำให้เกิดความสับสน เช่นเดียวกับsize_t
การกำหนดมาตรฐาน C89 wchar_t
, off_t
, ptrdiff_t
และอาจจะบางคนอื่น ๆ ฉันลืม มาตรฐาน C99 กำหนดมากชนิดพิเศษเช่นuintptr_t
, intmax_t
, int8_t
, uint_least16_t
, uint_fast32_t
และอื่น ๆ เหล่านี้ชนิดใหม่จะมีการกำหนดอย่างเป็นทางการใน<stdint.h>
แต่ส่วนใหญ่มักจะใช้<inttypes.h>
ที่ (ผิดปกติสำหรับส่วนหัวมาตรฐาน C) <stdint.h>
รวมถึง มัน ( <inttypes.h>
) ยังกำหนดแมโครสำหรับใช้กับและprintf()
scanf()
ดังที่ Matt Curtis ตั้งข้อสังเกตว่าไม่มีความสำคัญต่อคอมไพเลอร์ในคำต่อท้าย มันเป็นแบบแผนของมนุษย์
อย่างไรก็ตามคุณควรทราบว่าPOSIXกำหนดชื่อประเภทพิเศษจำนวนมากที่ลงท้ายด้วย ' _t
' และสำรองส่วนต่อท้ายสำหรับการใช้งาน ซึ่งหมายความว่าหากคุณกำลังทำงานกับระบบที่เกี่ยวข้องกับ POSIX การกำหนดชื่อประเภทของคุณเองด้วยอนุสัญญาจะไม่แนะนำ ระบบที่ฉันใช้ทำงานได้ทำไปแล้ว (มากกว่า 20 ปี); เราได้รับการสะดุดโดยระบบที่กำหนดประเภทด้วยชื่อเดียวกับที่เรากำหนด
abbr_xxxxx_t
ชื่อประเภท คุณอาจถูกจับได้ตลอดเวลาหากไม่มีคำนำหน้าเช่นนั้น โดยทั่วไปแล้ว_t
ประเภทที่ได้มาตรฐานจะใช้ตัวพิมพ์เล็กทั้งหมด ( FILE
และDIR
เป็นข้อยกเว้นสองข้อ, สองครั้ง - ตัวพิมพ์ใหญ่ทั้งหมดและไม่ใช่_t
) ดังนั้นคุณจึงสามารถใช้งานCamelCase_t
ด้วยความปลอดภัยระดับปานกลางโดยมีหรือไม่มีตัวพิมพ์ใหญ่ ระบบที่ฉันทำงานส่วนใหญ่มีแนวโน้มที่จะมีชีวิตอยู่อย่างเป็นอันตรายและใช้งาน_t
ต่อไป แต่มันก็กัดเราในบางโอกาส ฉันมักจะใช้CamelCase
โดยไม่ต้องมีคำต่อท้ายสำหรับงานของฉันเอง ฟังก์ชั่นของฉันมักจะเป็นตัวพิมพ์เล็กทั้งหมด
มันเป็นแบบแผนที่ใช้สำหรับการตั้งชื่อชนิดข้อมูลเช่นกับtypedef
:
typedef struct {
char* model;
int year;
...
} car_t;
_t
มักจะตัดคำนิยามชนิดทึบแสง
GCC เพียงเพิ่มชื่อที่ลงท้ายด้วย_t
กับ namespace สงวนคุณไม่สามารถใช้เพื่อหลีกเลี่ยงความขัดแย้งกับรุ่นอนาคตของมาตรฐาน C และ POSIX (คู่มือห้องสมุด GNU C) หลังจากการวิจัยบางอย่างในที่สุดฉันก็พบการอ้างอิงที่ถูกต้องใน POSIX Standard (1003.1, เหตุผล (ข้อมูล)):
B.2.12 ประเภทข้อมูล
ความต้องการที่ประเภทเพิ่มเติมที่กำหนดไว้ในส่วนนี้สิ้นสุดใน '' _t '' ได้รับแจ้งจากปัญหามลภาวะในพื้นที่ชื่อ เป็นการยากที่จะกำหนดประเภท (โดยที่ประเภทนั้นไม่ใช่หนึ่งประเภทที่กำหนดโดย IEEE Std 1003.1-2001) ในไฟล์ส่วนหัวหนึ่งไฟล์และใช้ในอีกส่วนหนึ่งโดยไม่เพิ่มสัญลักษณ์ในพื้นที่ชื่อของโปรแกรม เพื่อให้ผู้ใช้งานสามารถระบุประเภทของตัวเองได้แอปพลิเคชันที่สอดคล้องทั้งหมดจะต้องหลีกเลี่ยงสัญลักษณ์ที่ลงท้ายด้วย '' _t '' ซึ่งจะอนุญาตให้ผู้ดำเนินการจัดทำประเภทเพิ่มเติม เนื่องจากการใช้ชนิดที่สำคัญอยู่ในคำจำกัดความของสมาชิกโครงสร้างซึ่งสามารถเพิ่ม (และในหลาย ๆ กรณี) ให้กับโครงสร้างที่กำหนดไว้ใน IEEE Std 1003.1-2001 ความต้องการประเภทเพิ่มเติมจึงน่าสนใจ
สรุปมาตรฐานบอกว่ามีโอกาสที่ดีในการขยายรายการประเภทมาตรฐานดังนั้นมาตรฐานจึง จำกัด_t
เนมสเปซสำหรับการใช้งานของตัวเอง
ยกตัวอย่างเช่นโปรแกรมของคุณตรงกับPOSIX 1003.1 ปัญหา 6foo_t
และคุณกำหนดประเภทPOSIX 1003.1 ปัญหา 7foo_t
ถูกปล่อยออกมาในที่สุดก็มีประเภทที่กำหนดขึ้นใหม่ โปรแกรมของคุณไม่ตรงกับเวอร์ชันใหม่ซึ่งอาจมีปัญหา การ จำกัด การ_t
ใช้งานป้องกันไม่ให้มีการเปลี่ยนรหัสอีกครั้ง ดังนั้นถ้าคุณตั้งเป้าหมายให้เป็นไปตาม POSIX คุณควรหลีกเลี่ยงสิ่งที่_t
เป็นมาตรฐานระบุ
ด้านหมายเหตุ: ส่วนตัวฉันพยายามติด POSIX เพราะฉันคิดว่ามันให้พื้นฐานที่ดีสำหรับการเขียนโปรแกรมที่สะอาด นอกจากนี้ฉันชอบแนวทางการเขียนโค้ด Linux สไตล์ (บทที่ 5) มีเหตุผลที่ดีบางประการที่ไม่ใช้ typedef หวังว่าจะช่วยได้!
มันเป็นหลักการตั้งชื่อมาตรฐานสำหรับประเภทข้อมูลซึ่งมักจะกำหนดโดย typedefs รหัส C จำนวนมากที่เกี่ยวข้องกับการลงทะเบียนฮาร์ดแวร์ใช้ชื่อมาตรฐานที่กำหนดโดย C99 สำหรับชนิดข้อมูลขนาดคงที่ที่ลงนามและไม่ได้ลงชื่อ ตามแบบแผนชื่อเหล่านี้อยู่ในไฟล์ส่วนหัวมาตรฐาน (stdint.h) และลงท้ายด้วย _t
มันเป็นเพียงแค่การประชุมซึ่งหมายถึง "ประเภท" แปลว่าไม่มีอะไรพิเศษสำหรับคอมไพเลอร์
_t
ไม่เนื้อแท้มีความหมายพิเศษใด ๆ แต่มันได้ตกลงไปในการใช้งานทั่วไปเพื่อเพิ่ม_t
คำต่อท้ายเพื่อ typedef ของ
คุณอาจคุ้นเคยกับวิธีปฏิบัติ C ทั่วไปสำหรับการตั้งชื่อตัวแปร ... มันคล้ายกับว่ามันเป็นเรื่องปกติที่จะติด ap ที่ด้านหน้าสำหรับตัวชี้และใช้ขีดล่างหน้าตัวแปรทั่วโลก และจะใช้ชื่อตัวแปรi
, j
และk
สำหรับตัวแปรวงชั่วคราว
ในรหัสที่ขนาดคำและการสั่งซื้อเป็นสิ่งสำคัญมันเป็นเรื่องธรรมดามากที่จะใช้ประเภทที่กำหนดเองที่ชัดเจนเช่นBYTE
WORD
(ปกติ 16 บิต) DWORD
(32 บิต)
int_t
ไม่ดีนักเนื่องจากคำจำกัดความของความint
แตกต่างระหว่างแพลตฟอร์ม - ดังนั้นint
คุณจะทำตามใคร (แม้ว่าทุกวันนี้การพัฒนาโดยใช้พีซีเป็นศูนย์กลางส่วนใหญ่จะถือว่าเป็น 32 บิต แต่สิ่งที่มากมายสำหรับการพัฒนาที่ไม่ใช่พีซียังคงถือว่าเป็น 16 บิตของ int)
มันหมายถึงประเภท size_t
เป็นประเภทขนาด
มีคำอธิบายที่ดีเกี่ยวกับเรื่องนี้อยู่บ้าง เพียงเพิ่มเหตุผลอื่นเพื่อกำหนดประเภทอีกครั้ง:
ในโครงการฝังตัวหลายประเภททุกประเภทจะถูกกำหนดใหม่เพื่อระบุขนาดที่กำหนดให้กับประเภทและเพื่อปรับปรุงความสามารถในการพกพาข้ามแพลตฟอร์มที่แตกต่างกัน (เช่นคอมไพเลอร์ประเภทฮาร์ดแวร์)
อีกเหตุผลหนึ่งก็คือการทำให้รหัสของคุณพกพาได้ในระบบปฏิบัติการที่แตกต่างกันและเพื่อหลีกเลี่ยงการชนกับประเภทที่มีอยู่ในระบบปฏิบัติการที่คุณกำลังรวมไว้ในรหัสของคุณ สำหรับสิ่งนี้มักจะมีการเพิ่มคำนำหน้า (ที่เป็นไปได้) ที่ไม่ซ้ำกัน
ตัวอย่าง:
typedef unsigned long dc_uint32_t;
หากคุณกำลังจัดการกับรหัสอินเทอร์เฟซฮาร์ดแวร์ผู้เขียนรหัสที่คุณกำลังดูอยู่อาจถูกกำหนดint_t
ให้เป็นจำนวนเต็มขนาดเฉพาะ มาตรฐาน C ไม่ได้กำหนดขนาดเฉพาะให้กับint
ประเภท (ขึ้นอยู่กับคอมไพเลอร์และแพลตฟอร์มเป้าหมายของคุณ) และการใช้int_t
ประเภทเฉพาะจะหลีกเลี่ยงปัญหาการพกพานั้น
นี่เป็นการพิจารณาที่สำคัญอย่างยิ่งสำหรับรหัสฮาร์ดแวร์ส่วนติดต่อซึ่งอาจเป็นสาเหตุที่คุณสังเกตเห็นการประชุมครั้งแรก
ตัวอย่างเช่นใน C99, /usr/include/stdint.h:
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
_t
มักจะหมายถึงกำหนดโดย typedef
int_t
กำหนด? หากมีการกำหนดไว้เสมอว่าint
ไม่มีประโยชน์ มันชัดเจนกว่าที่จะใช้int
โดยตรง หากไม่ได้กำหนดไว้เสมอint
(พูดว่าถ้าเป็นได้long int
หรืออาจเป็นไปได้short int
) ก็เป็นชื่อที่เลือกและสร้างความสับสน