O que um tipo seguido por _t (sublinhado-t) representa?

261

Parece uma pergunta simples, mas não consigo encontrá-la na pesquisa Stack Overflow ou no Google. O que um tipo seguido por uma _tmédia? Tal como

int_t anInt;

Eu vejo muito isso no código C destinado a lidar de perto com o hardware - não posso deixar de pensar que eles estão relacionados.

Kevin Griffin
fonte
3
Onde é int_tdefinido? Se é sempre definido como int, não é útil; é muito mais claro usar intdiretamente. Se nem sempre é definido como int(digamos, se poderia ser long intou short int), então é um nome mal escolhido e confuso.
21715 Keith Thompson

Respostas:

213

Como Douglas Mayle observou, basicamente denota um nome de tipo. Consequentemente, seria desaconselhável terminar com nomes de variáveis ​​ou funções com ' _t', pois isso pode causar alguma confusão. Bem como size_t, os norma define C89 wchar_t, off_t, ptrdiff_t, e, provavelmente, alguns outros que eu esqueci. O padrão C99 define um monte de tipos de extras, como uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, e assim por diante. Esses novos tipos são formalmente definidos, <stdint.h>mas na maioria das vezes você usará o <inttypes.h>que ( normalmente para cabeçalhos C padrão) inclui <stdint.h>. Ele ( <inttypes.h>) também define macros para uso com o printf()e scanf().

Como Matt Curtis observou, não há significado para o compilador no sufixo; é uma convenção voltada para o ser humano.

No entanto, você também deve observar que o POSIX define muitos nomes de tipos extras que terminam em ' _t' e reserva o sufixo para a implementação. Isso significa que, se você estiver trabalhando em sistemas relacionados ao POSIX, é aconselhável definir seus próprios nomes de tipo com a convenção. O sistema em que trabalho o faz (há mais de 20 anos); regularmente viajamos por sistemas que definem tipos com o mesmo nome que definimos.

Jonathan Leffler
fonte
4
parece razoável que o SO e as bibliotecas comuns de tempo de execução definam tipos com nomes genéricos; mas os tipos da sua empresa também não devem ser anexados com um prefixo ou algo assim?
Toybuilder 23/10/08
17
Eu uso _type em vez de _t nos meus typedefs precisamente para evitar isso.
CesarB
4
@ Jonathan Leffler - Que convenção de nomenclatura você usaria para tipos definidos pelo usuário?
J. Andrew Laughlin
15
@ Andrew: se você possui uma abreviação conveniente para usar como prefixo, pode ser seguro usar abbr_xxxxx_tnomes de tipos. Sem esse prefixo, você pode ser pego a qualquer momento. Geralmente, os _ttipos padronizados usam todas as letras minúsculas ( FILEe DIRsão duas exceções, duas vezes - todas maiúsculas e não _t); portanto, você pode usar CamelCase_tcom segurança moderada, com ou sem as maiúsculas à esquerda. O sistema em que trabalho principalmente tende a viver perigosamente e a usar de _tqualquer maneira, mas nos incomodou algumas vezes. Costumo usar CamelCasesem sufixo o meu próprio trabalho; minhas funções geralmente são todas minúsculas.
Jonathan Leffler
5
@ JonathanLeffler, comecei a usar essa convenção, CamelCase para tipos, lower_case para funções. Eu procurei nesta pergunta esperando não ser o único. Obrigado pela validação!
Austin Mullins
50

É uma convenção usada para nomear tipos de dados, por exemplo, com typedef:


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

mmacaulay
fonte
43

O _tgeralmente envolve uma definição de tipo opaco.

O GCC apenas adiciona nomes que terminam com _to espaço para nome reservado que você não pode usar, para evitar conflitos com versões futuras do Standard C e POSIX (manual da biblioteca GNU C) . Após algumas pesquisas, finalmente encontrei a referência correta dentro do padrão POSIX (1003.1, Justificativa (Informativa)):

B.2.12 Tipos de dados

O requisito de que tipos adicionais definidos nesta seção terminem em '' _t '' foi motivado pelo problema da poluição do espaço de nome. É difícil definir um tipo (em que esse tipo não seja definido pelo IEEE Std 1003.1-2001) em um arquivo de cabeçalho e usá-lo em outro sem adicionar símbolos ao espaço para nome do programa. Para permitir que os implementadores forneçam seus próprios tipos, todos os aplicativos em conformidade são necessários para evitar que os símbolos terminem em '' _t '', o que permite que o implementador forneça tipos adicionais. Como um uso principal de tipos está na definição de membros da estrutura, que pode (e em muitos casos deve) ser adicionado às estruturas definidas no IEEE Std 1003.1-2001, a necessidade de tipos adicionais é atraente.

Em poucas palavras, o Padrão diz que há boas chances de estender a lista de tipos de Padrão; portanto, o Padrão restringe o _tespaço de nome para seu próprio uso.

Por exemplo, seu programa corresponde ao POSIX 1003.1 Edições 6 e você definiu um tipo foo_t. O POSIX 1003.1 Edições 7 é finalmente lançado com um tipo recém-definido foo_t. Seu programa não corresponde à nova versão, o que pode ser um problema. A restrição do _tuso impede a refatoração do código. Portanto, se você busca uma conformidade com POSIX, deve definitivamente evitar o _tque o Padrão declara.

Nota lateral: pessoalmente, eu tento manter o POSIX porque acho que ele fornece bons conceitos básicos para uma programação limpa. Além disso, gosto bastante das diretrizes do Linux Coding Style (capítulo 5) . Existem algumas boas razões para não usar o typedef. Espero que esta ajuda!

Benoit
fonte
18

É uma convenção de nomenclatura padrão para tipos de dados, geralmente definida por typedefs. Muitos códigos C que lidam com registros de hardware usam nomes padrão definidos por C99 para tipos de dados de tamanho fixo assinados e não assinados. Como convenção, esses nomes estão em um arquivo de cabeçalho padrão (stdint.h) e terminam com _t.

mkClark
fonte
11

É apenas uma convenção que significa "tipo". Isso não significa nada de especial para o compilador.

Matt Curtis
fonte
11

O _tnão possui inerentemente nenhum significado especial. Mas caiu em uso comum adicionar o _tsufixo aos typedef's.

Você pode estar mais familiarizado com práticas comuns de C para nomeação de variáveis ​​... Isso é semelhante a como é comum colocar ap na frente de um ponteiro e usar um sublinhado na frente de variáveis ​​globais (isso é um pouco menos comum) e usar os nomes de variáveis i, je kpara as variáveis de loop temporários.

No código em que o tamanho e a ordem das palavras são importantes, é muito comum usar tipos definidos personalizados que são explícitos, como BYTE WORD(normalmente 16 bits) DWORD(32 bits).

int_tnão é tão bom, porque a definição de intvaria entre plataformas - então de quem intvocê está em conformidade? (Embora, atualmente, a maioria dos desenvolvimentos centrados em PC trate-o como 32 bits, muitas coisas para desenvolvimento não-PC ainda tratam int's como 16 bits).

Construtor de brinquedos
fonte
10

Isso significa tipo. size_té o tipo de tamanho.

Douglas Mayle
fonte
8

Houve algumas boas explicações sobre o assunto. Apenas para adicionar outro motivo para redefinir os tipos:

Em muitos projetos incorporados, todos os tipos são redefinidos para indicar corretamente o tamanho especificado para os tipos e melhorar a portabilidade em diferentes plataformas (por exemplo, compiladores de tipos de hardware).

Outro motivo será tornar seu código portátil em diferentes sistemas operacionais e evitar colisões com tipos existentes no sistema operacional que você está integrando ao seu código. Para isso, geralmente é adicionado um prefixo exclusivo (quanto possível).

Exemplo:

typedef unsigned long dc_uint32_t;
Ilya
fonte
7

Se você estiver lidando com código de interface de hardware, o autor do código que você está visualizando pode ter definido int_tcomo um número inteiro de tamanho específico. O padrão C não atribui um tamanho específico ao inttipo (depende do seu compilador e plataforma de destino, potencialmente), e o uso de um int_ttipo específico evitaria esse problema de portabilidade.

Essa é uma consideração particularmente importante para o código da interface de hardware, e pode ser por isso que você notou a convenção pela primeira vez.

Greg Hewgill
fonte
1
isso não será uma prática muito boa, eu esperaria que alguém definisse [u] int_ [32 16 8] _t para deixar claro qual é o tamanho que você está definindo.
Ilya
1
Você está certo, "int_t" por si só diz ao programador que é um tipo definido pelo usuário, mas não o que realmente é!
Greg Hewgill 24/10/08
0

Por exemplo, em 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 sempre significa definido por typedef.

Jayhello
fonte