Một loại theo sau _t (gạch dưới-t) đại diện cho cái gì?


261

Đây có vẻ là một câu hỏi đơn giản, nhưng tôi không thể tìm thấy nó với tìm kiếm Stack Overflow hoặc Google. Một loại theo sau _tcó nghĩa là gì? Nhu la

int_t anInt;

Tôi thấy nó rất nhiều trong mã C có nghĩa là để đối phó chặt chẽ với phần cứng. Tôi không thể không nghĩ rằng chúng có liên quan.


3
Trường hợp được int_txác định? Nếu nó luôn được định nghĩa là int, nó không hữu ích; Nó rõ ràng hơn nhiều để sử dụng inttrực tiếp. Nếu nó không phải luôn luôn được định nghĩa là int(giả sử, nếu nó có thể long inthoặc short int), thì đó là một cái tên được lựa chọn kém và khó hiểu.
Keith Thompson

Câu trả lời:


213

Như Douglas Mayle đã lưu ý, về cơ bản nó biểu thị một tên loại. Do đó, bạn sẽ không nên kết thúc tên biến hoặc hàm với ' _t' vì nó có thể gây ra một số nhầm lẫn. Cũng như size_t, các định nghĩa tiêu chuẩn C89 wchar_t, off_t, ptrdiff_t, và có lẽ một số người khác tôi đã quên. Các tiêu chuẩn C99 xác định rất nhiều loại phụ, chẳng hạn như uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, và vân vân. Các loại mới này được định nghĩa chính thức trong <stdint.h>nhưng thường thì bạn sẽ sử dụng <inttypes.h>loại nào (bất thường cho các tiêu đề C tiêu chuẩn) bao gồm <stdint.h>. Nó ( <inttypes.h>) cũng định nghĩa các macro để sử dụng với printf()scanf().

Như Matt Curtis đã lưu ý, không có ý nghĩa đối với trình biên dịch trong hậu tố; đó là một quy ước định hướng của con người.

Tuy nhiên, bạn cũng cần lưu ý rằng POSIX định nghĩa rất nhiều tên loại bổ sung kết thúc bằng ' _t' và bảo lưu hậu tố cho việc triển khai. Điều đó có nghĩa là nếu bạn đang làm việc trên các hệ thống liên quan đến POSIX, việc xác định tên loại của riêng bạn với quy ước là không nên. Hệ thống tôi làm việc đã thực hiện nó (trong hơn 20 năm); chúng tôi thường xuyên bị vấp ngã bởi các hệ thống xác định loại có cùng tên như chúng tôi xác định.


4
Có vẻ hợp lý khi các hệ điều hành và thư viện thời gian chạy chung xác định các loại có tên chung; nhưng các loại hình công ty của bạn cũng không nên được thêm tiền tố hay cái gì đó?
Toybuilder

17
Tôi sử dụng _type thay vì _t trên typedefs của mình một cách chính xác để tránh điều đó.
CesarB

4
@Jonathan Leffler - Bạn sẽ sử dụng quy ước đặt tên nào cho các loại do người dùng xác định?
J. Andrew Smilelin

15
@Andrew: nếu bạn có một từ viết tắt thuận tiện để sử dụng làm tiền tố, thì bạn có thể an toàn khi sử dụng abbr_xxxxx_ttên loại. Nếu không có tiền tố như vậy, bạn có thể bị bắt bất cứ lúc nào. Nói chung, các _tloại được tiêu chuẩn hóa sử dụng tất cả các chữ thường ( FILEDIRlà hai ngoại lệ, hai lần - tất cả các chữ hoa và không _t), vì vậy bạn có thể sử dụng CamelCase_tvới độ an toàn vừa phải, có hoặc không có các chữ hoa hàng đầu. Hệ thống tôi chủ yếu hoạt động có xu hướng sống nguy hiểm và sử dụng bằng _tmọi cách, nhưng nó đã cắn chúng tôi trong các dịp. Tôi có xu hướng sử dụng CamelCasemà không có hậu tố cho công việc của riêng tôi; chức năng của tôi thường là tất cả các trường hợp thấp hơn.
Jonathan Leffler

5
@JonathanLeffler, tôi đã bắt đầu sử dụng quy ước đó, CamelCase cho các loại, low_case cho các hàm. Tôi đã tìm kiếm câu hỏi này với hy vọng tôi không phải là người duy nhất. Cảm ơn đã xác nhận!
Austin Mullins

50

Đó là một quy ước được sử dụng để đặt tên các loại dữ liệu, ví dụ typedef:


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


43

Các _tthường kết thúc một định nghĩa loại mờ.

GCC chỉ thêm các tên kết thúc _tvào không gian tên dành riêng mà bạn không thể sử dụng, để tránh xung đột với các phiên bản tương lai của Standard C và POSIX (hướng dẫn thư viện GNU C) . Sau một số nghiên cứu, cuối cùng tôi đã tìm thấy tài liệu tham khảo chính xác bên trong Tiêu chuẩn POSIX (1003.1, Cơ sở lý luận (Thông tin)):

B.2.12 Kiểu dữ liệu

Yêu cầu rằng các loại bổ sung được xác định trong phần này kết thúc bằng '' _t '' đã được nhắc nhở bởi vấn đề ô nhiễm không gian tên. Thật khó để xác định một loại (trong đó loại đó không phải là một loại được xác định bởi IEEE Std 1003.1-2001) trong một tệp tiêu đề và sử dụng nó trong một loại khác mà không thêm các ký hiệu vào không gian tên của chương trình. Để cho phép người triển khai cung cấp các loại riêng của họ, tất cả các ứng dụng phù hợp được yêu cầu để tránh các ký hiệu kết thúc bằng '' _t '', cho phép người triển khai cung cấp các loại bổ sung. Bởi vì việc sử dụng chính các loại là trong định nghĩa của các thành viên cấu trúc, có thể (và trong nhiều trường hợp phải) được thêm vào các cấu trúc được định nghĩa trong IEEE Std 1003.1-2001, nên nhu cầu về các loại bổ sung là hấp dẫn.

Tóm lại, Tiêu chuẩn nói rằng có nhiều cơ hội mở rộng danh sách các loại Tiêu chuẩn, do đó, Tiêu chuẩn hạn chế _tkhông gian tên để sử dụng riêng.

Chẳng hạn, chương trình của bạn phù hợp với POSIX 1003.1 Vấn đề 6 và bạn đã xác định một loại foo_t. POSIX 1003.1 Các vấn đề 7 cuối cùng được phát hành với một loại mới được xác định foo_t. Chương trình của bạn không phù hợp với phiên bản mới, đây có thể là một vấn đề. Hạn chế _tsử dụng ngăn chặn tái cấu trúc mã. Do đó, nếu bạn nhắm đến sự tuân thủ POSIX, bạn chắc chắn nên tránh _tnhư Tiêu chuẩn quy định.

Lưu ý bên lề: cá nhân, tôi cố gắng gắn bó với POSIX vì tôi nghĩ rằng nó mang lại những điều cơ bản tốt cho lập trình sạch. Hơn nữa, tôi khá thích các hướng dẫn về Phong cách mã hóa Linux (chương 5) . Có một số lý do tốt tại sao không sử dụng typedef. Hy vọng điều này giúp đỡ!


18

Đây là một quy ước đặt tên tiêu chuẩn cho các loại dữ liệu, thường được xác định bởi typedefs. Rất nhiều mã C liên quan đến các thanh ghi phần cứng sử dụng tên tiêu chuẩn do C99 xác định cho các kiểu dữ liệu có kích thước cố định được ký và không dấu. Theo quy ước, các tên này nằm trong tệp tiêu đề chuẩn (stdint.h) và kết thúc bằng _t.


11

Nó chỉ là một quy ước có nghĩa là "loại". Nó có nghĩa là không có gì đặc biệt cho trình biên dịch.


11

Việc _tvốn dĩ không có bất kỳ ý nghĩa đặc biệt. Nhưng nó đã được sử dụng phổ biến để thêm _thậu tố vào typedef's.

Bạn có thể quen thuộc hơn với các cách thực hành C phổ biến để đặt tên biến ... Điều này tương tự như cách phổ biến để dán ap ở phía trước cho một con trỏ và sử dụng dấu gạch dưới trước các biến toàn cục (điều này ít phổ biến hơn một chút) , và sử dụng các tên biến i, jkcho các biến vòng lặp tạm thời.

Trong mã trong đó kích thước từ và thứ tự là quan trọng, rất phổ biến để sử dụng các loại được xác định tùy chỉnh rõ ràng, chẳng hạn như BYTE WORD(thông thường là 16 bit) DWORD(32 bit).

int_tlà không tốt, bởi vì định nghĩa intkhác nhau giữa các nền tảng - vậy intbạn đang tuân thủ theo ai? (Mặc dù, ngày nay, hầu hết sự phát triển tập trung vào PC coi nó là 32 bit, nhiều thứ cho sự phát triển không phải của PC vẫn coi int là 16 bit).



8

Có một vài lời giải thích tốt về chủ đề này. Chỉ cần thêm một lý do khác để xác định lại các loại:

Trong nhiều dự án nhúng, tất cả các loại được xác định lại để nêu chính xác kích thước đã cho cho các loại và để cải thiện tính di động trên các nền tảng khác nhau (tức là trình biên dịch loại phần cứng).

Một lý do khác sẽ là làm cho mã của bạn có thể di động trên các HĐH khác nhau và để tránh xung đột với các loại hiện có trong HĐH mà bạn đang tích hợp trong mã của mình. Đối với điều này, thường là một tiền tố duy nhất (có thể) được thêm vào.

Thí dụ:

typedef unsigned long dc_uint32_t;

7

Nếu bạn đang xử lý mã giao diện phần cứng, tác giả của mã bạn đang xem có thể đã xác định int_tlà một số nguyên kích thước cụ thể. Tiêu chuẩn C không chỉ định kích thước cụ thể cho intloại (có thể phụ thuộc vào trình biên dịch và nền tảng đích của bạn) và sử dụng một int_tloại cụ thể sẽ tránh được vấn đề về tính di động đó.

Đây là một xem xét đặc biệt quan trọng đối với mã giao diện phần cứng, có thể là lý do tại sao bạn lần đầu tiên nhận thấy quy ước ở đó.


1
điều này sẽ không thực tế lắm, tôi mong người ta định nghĩa [u] int_ [32 16 8] _t để làm rõ kích thước bạn xác định là gì.
Ilya

1
Bạn hoàn toàn đúng, "int_t" tự nó nói với lập trình viên rằng đó là loại do người dùng xác định nhưng không phải là loại thực sự!
Greg Hewgill

0

Ví dụ: trong 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 luôn có nghĩa là xác định bởi typedef.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.