ประเภทที่ตามด้วย _t (ขีดล่าง -t) หมายถึงอะไร


261

ดูเหมือนว่าเป็นคำถามง่าย ๆ แต่ฉันไม่พบด้วยการค้นหา Stack Overflow หรือ Google ประเภทใดตามด้วย_tค่าเฉลี่ย เช่น

int_t anInt;

ฉันเห็นรหัส C จำนวนมากเพื่อจัดการกับฮาร์ดแวร์อย่างใกล้ชิดฉันอดไม่ได้ที่จะคิดว่ามันเกี่ยวข้องกัน


3
อยู่ที่ไหนint_tกำหนด? หากมีการกำหนดไว้เสมอว่าintไม่มีประโยชน์ มันชัดเจนกว่าที่จะใช้intโดยตรง หากไม่ได้กำหนดไว้เสมอint(พูดว่าถ้าเป็นได้long intหรืออาจเป็นไปได้short int) ก็เป็นชื่อที่เลือกและสร้างความสับสน
Keith Thompson

คำตอบ:


213

อย่างที่ทราบกันแล้วว่าดักลาส 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 ปี); เราได้รับการสะดุดโดยระบบที่กำหนดประเภทด้วยชื่อเดียวกับที่เรากำหนด


4
ดูเหมือนว่าสมเหตุสมผลแล้วที่ OS และไลบรารีรันไทม์ทั่วไปกำหนดชนิดที่มีชื่อสามัญ แต่ประเภทของ บริษัท ของคุณไม่ควรมีคำนำหน้าหรืออะไรบางอย่าง
Toybuilder

17
ฉันใช้ _type แทน _t บน typedefs ของฉันอย่างแม่นยำเพื่อหลีกเลี่ยงปัญหานั้น
CesarB

4
@Jonathan Leffler - คุณมีข้อตกลงในการตั้งชื่อแบบใดสำหรับประเภทที่ผู้ใช้กำหนด?
J. Andrew Laughlin

15
@Andrew: หากคุณมีตัวย่อที่สะดวกในการใช้เป็นคำนำหน้าคุณอาจปลอดภัยที่จะใช้abbr_xxxxx_tชื่อประเภท คุณอาจถูกจับได้ตลอดเวลาหากไม่มีคำนำหน้าเช่นนั้น โดยทั่วไปแล้ว_tประเภทที่ได้มาตรฐานจะใช้ตัวพิมพ์เล็กทั้งหมด ( FILEและDIRเป็นข้อยกเว้นสองข้อ, สองครั้ง - ตัวพิมพ์ใหญ่ทั้งหมดและไม่ใช่_t) ดังนั้นคุณจึงสามารถใช้งานCamelCase_tด้วยความปลอดภัยระดับปานกลางโดยมีหรือไม่มีตัวพิมพ์ใหญ่ ระบบที่ฉันทำงานส่วนใหญ่มีแนวโน้มที่จะมีชีวิตอยู่อย่างเป็นอันตรายและใช้งาน_tต่อไป แต่มันก็กัดเราในบางโอกาส ฉันมักจะใช้CamelCaseโดยไม่ต้องมีคำต่อท้ายสำหรับงานของฉันเอง ฟังก์ชั่นของฉันมักจะเป็นตัวพิมพ์เล็กทั้งหมด
Jonathan Leffler

5
@JonathanLeffler ฉันเริ่มใช้การประชุมนั้น CamelCase สำหรับประเภท, lower_case สำหรับฟังก์ชั่น ฉันค้นหาคำถามนี้หวังว่าฉันจะไม่ใช่คนเดียว ขอบคุณสำหรับการตรวจสอบ!
Austin Mullins

50

มันเป็นแบบแผนที่ใช้สำหรับการตั้งชื่อชนิดข้อมูลเช่นกับtypedef:


typedef struct {
  char* model;
  int year;
...
} car_t;


43

_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 หวังว่าจะช่วยได้!


18

มันเป็นหลักการตั้งชื่อมาตรฐานสำหรับประเภทข้อมูลซึ่งมักจะกำหนดโดย typedefs รหัส C จำนวนมากที่เกี่ยวข้องกับการลงทะเบียนฮาร์ดแวร์ใช้ชื่อมาตรฐานที่กำหนดโดย C99 สำหรับชนิดข้อมูลขนาดคงที่ที่ลงนามและไม่ได้ลงชื่อ ตามแบบแผนชื่อเหล่านี้อยู่ในไฟล์ส่วนหัวมาตรฐาน (stdint.h) และลงท้ายด้วย _t



11

_tไม่เนื้อแท้มีความหมายพิเศษใด ๆ แต่มันได้ตกลงไปในการใช้งานทั่วไปเพื่อเพิ่ม_tคำต่อท้ายเพื่อ typedef ของ

คุณอาจคุ้นเคยกับวิธีปฏิบัติ C ทั่วไปสำหรับการตั้งชื่อตัวแปร ... มันคล้ายกับว่ามันเป็นเรื่องปกติที่จะติด ap ที่ด้านหน้าสำหรับตัวชี้และใช้ขีดล่างหน้าตัวแปรทั่วโลก และจะใช้ชื่อตัวแปรi, jและkสำหรับตัวแปรวงชั่วคราว

ในรหัสที่ขนาดคำและการสั่งซื้อเป็นสิ่งสำคัญมันเป็นเรื่องธรรมดามากที่จะใช้ประเภทที่กำหนดเองที่ชัดเจนเช่นBYTE WORD(ปกติ 16 บิต) DWORD(32 บิต)

int_tไม่ดีนักเนื่องจากคำจำกัดความของความintแตกต่างระหว่างแพลตฟอร์ม - ดังนั้นintคุณจะทำตามใคร (แม้ว่าทุกวันนี้การพัฒนาโดยใช้พีซีเป็นศูนย์กลางส่วนใหญ่จะถือว่าเป็น 32 บิต แต่สิ่งที่มากมายสำหรับการพัฒนาที่ไม่ใช่พีซียังคงถือว่าเป็น 16 บิตของ int)



8

มีคำอธิบายที่ดีเกี่ยวกับเรื่องนี้อยู่บ้าง เพียงเพิ่มเหตุผลอื่นเพื่อกำหนดประเภทอีกครั้ง:

ในโครงการฝังตัวหลายประเภททุกประเภทจะถูกกำหนดใหม่เพื่อระบุขนาดที่กำหนดให้กับประเภทและเพื่อปรับปรุงความสามารถในการพกพาข้ามแพลตฟอร์มที่แตกต่างกัน (เช่นคอมไพเลอร์ประเภทฮาร์ดแวร์)

อีกเหตุผลหนึ่งก็คือการทำให้รหัสของคุณพกพาได้ในระบบปฏิบัติการที่แตกต่างกันและเพื่อหลีกเลี่ยงการชนกับประเภทที่มีอยู่ในระบบปฏิบัติการที่คุณกำลังรวมไว้ในรหัสของคุณ สำหรับสิ่งนี้มักจะมีการเพิ่มคำนำหน้า (ที่เป็นไปได้) ที่ไม่ซ้ำกัน

ตัวอย่าง:

typedef unsigned long dc_uint32_t;

7

หากคุณกำลังจัดการกับรหัสอินเทอร์เฟซฮาร์ดแวร์ผู้เขียนรหัสที่คุณกำลังดูอยู่อาจถูกกำหนดint_tให้เป็นจำนวนเต็มขนาดเฉพาะ มาตรฐาน C ไม่ได้กำหนดขนาดเฉพาะให้กับintประเภท (ขึ้นอยู่กับคอมไพเลอร์และแพลตฟอร์มเป้าหมายของคุณ) และการใช้int_tประเภทเฉพาะจะหลีกเลี่ยงปัญหาการพกพานั้น

นี่เป็นการพิจารณาที่สำคัญอย่างยิ่งสำหรับรหัสฮาร์ดแวร์ส่วนติดต่อซึ่งอาจเป็นสาเหตุที่คุณสังเกตเห็นการประชุมครั้งแรก


1
นี่จะไม่ใช่แนวปฏิบัติที่ดีมากฉันคาดหวังให้มีคนนิยาม [u] int_ [32 16 8] _t เพื่อให้ชัดเจนว่าขนาดที่คุณกำหนดนั้นเป็นอย่างไร
Ilya

1
คุณค่อนข้างถูกต้อง "int_t" ด้วยตัวเองบอกโปรแกรมเมอร์ว่าเป็นชนิดที่ผู้ใช้กำหนด แต่ไม่ใช่สิ่งที่เป็นจริง!
Greg Hewgill

0

ตัวอย่างเช่นใน 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.