Os arquivos de cabeçalho stdlib.he stddef.h definem um tipo de dados chamado size_t que é usado para representar o tamanho de um objeto. As funções de biblioteca que usam tamanhos esperam que sejam do tipo size_t, e o operador sizeof é avaliado como size_t.
O tipo real de size_t depende da plataforma; um erro comum é assumir que size_t é o mesmo que int não assinado, o que pode levar a erros de programação, principalmente quando as arquiteturas de 64 bits se tornam mais prevalentes.
@ NDEthos Depende! Nisto, aqui o Linux /usr/include/stdlib.hobtém a definição /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.he nela é padronizado, a long unsigned intmenos que outro arquivo de cabeçalho diga o contrário.
David Tonhofer 4/16/16
1
Confirmo size_t para int tuncation é perigoso . Isso pode ser estranho, mas como escrever um patch sozinho para corrigir esse tipo de erro quando ocorre milhares de vezes no kernel do linux?
precisa saber é o seguinte
36
size_t é o tipo usado para representar tamanhos (como o próprio nome indica). Sua plataforma (e até potencialmente implementação) depende e deve ser usada apenas para esse fim. Obviamente, representando um tamanho, size_t não está assinado. Muitas funções stdlib, incluindo malloc, sizeof e várias funções de operação de string, usam size_t como um tipo de dados.
Um int é assinado por padrão e, embora seu tamanho também seja dependente da plataforma, ele terá 32 bits fixos na maioria das máquinas modernas (e embora size_t seja de 64 bits na arquitetura de 64 bits, o int permanece 32 bits nessas arquiteturas).
Para resumir: use size_t para representar o tamanho de um objeto e int (ou long) em outros casos.
O size_ttipo é definido como o tipo integral não assinado do sizeofoperador. No mundo real, você verá intdefinido como 32 bits (para compatibilidade com versões anteriores), mas size_tdefinido como 64 bits (para poder declarar matrizes e estruturas com mais de 4 GiB de tamanho) em plataformas de 64 bits. Se a long inttambém tiver 64 bits, isso é chamado de convenção LP64; se long inttiver 32 bits, long long inte os ponteiros tiverem 64 bits, é LLP64. Você também pode obter o inverso, um programa que usa instruções de 64 bits para velocidade, mas ponteiros de 32 bits para economizar memória. Além disso, intestá assinado e size_tnão está assinado.
Historicamente, havia várias outras plataformas em que os endereços eram maiores ou menores que o tamanho nativo de int. De fato, nos anos 70 e início dos anos 80, isso era mais comum do que não: todos os microcomputadores populares de 8 bits tinham registradores e endereços de 16 bits e a transição entre 16 e 32 bits também produziu muitas máquinas que tinham endereços mais amplos que seus registros. Ocasionalmente, ainda vejo perguntas aqui sobre o Borland Turbo C para MS-DOS, cujo modo de memória Enorme tinha endereços de 20 bits armazenados em 32 bits em uma CPU de 16 bits (mas que suportava o conjunto de instruções de 32 bits do 80386); o Motorola 68000 tinha uma ALU de 16 bits com registros e endereços de 32 bits; havia mainframes da IBM com endereços de 15, 24 ou 31 bits. Você também vê diferentes tamanhos de ALU e de barramento de endereços em sistemas incorporados.
Quando o tempo inté menor size_te você tenta armazenar o tamanho ou deslocamento de um arquivo ou objeto muito grande em um unsigned int, existe a possibilidade de que ele possa estourar e causar um bug. Com um int, há também a possibilidade de obter um número negativo. Se um intou unsigned intfor maior, o programa será executado corretamente, mas desperdiçará memória.
Geralmente, você deve usar o tipo correto para esse fim, se quiser portabilidade. Muitas pessoas recomendam que você use matemática assinada em vez de não assinada (para evitar erros sutis e desagradáveis 1U < -3). Para o efeito, os define biblioteca padrão ptrdiff_tem <stddef.h>como o tipo assinada do resultado da subtração um ponteiro de outro.
Dito isso, uma solução alternativa pode ser verificar os limites de todos os endereços e compensações contra INT_MAXe / 0ou INT_MINconforme apropriado e ativar os avisos do compilador sobre a comparação de quantidades assinadas e não assinadas, caso você perca alguma. Você deve sempre, sempre, sempre verificar os acessos de sua matriz quanto a estouro em C de qualquer maneira.
Eu acho que size_t é realmente garantido como um alias para um número inteiro não assinado, então não pode ser uma estrutura. No entanto, não tenho uma referência útil para fazer backup disso agora.
desenrolamento
9
@unwind: C99: TC3, 7,17 §2
Christoph
1
@danio Por que é assim? Você pode explicar?
Abutre de Rüppell
2
Eu não ligaria para o cplusplus se fosse você! Se você não pode citar capítulos, versículos, parágrafos e linhas, tudo é boato! :-)
graham.reeds
1
size_té especificado como um tipo inteiro não assinado . C11 §6.5.3.4 5 "O valor do resultado de ambos os operadores ( sizeof_Alignof) é definido pela implementação e seu tipo (um tipo inteiro não assinado) é size_t".
SIZE_Té um ULONG_PTRnúmero máximo de bytes para o qual um ponteiro pode apontar.
Este tipo é declarado da seguinte maneira:
typedef ULONG_PTR SIZE_T;
A ULONG_PTRé um tipo longo não assinado usado para precisão do ponteiro. É usado ao converter um ponteiro para um tipo longo para executar a aritmética do ponteiro.
Respostas:
Da amigável Wikipedia :
Além disso, verifique Por que o size_t é importante
fonte
/usr/include/stdlib.h
obtém a definição/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
e nela é padronizado, along unsigned int
menos que outro arquivo de cabeçalho diga o contrário.size_t é o tipo usado para representar tamanhos (como o próprio nome indica). Sua plataforma (e até potencialmente implementação) depende e deve ser usada apenas para esse fim. Obviamente, representando um tamanho, size_t não está assinado. Muitas funções stdlib, incluindo malloc, sizeof e várias funções de operação de string, usam size_t como um tipo de dados.
Um int é assinado por padrão e, embora seu tamanho também seja dependente da plataforma, ele terá 32 bits fixos na maioria das máquinas modernas (e embora size_t seja de 64 bits na arquitetura de 64 bits, o int permanece 32 bits nessas arquiteturas).
Para resumir: use size_t para representar o tamanho de um objeto e int (ou long) em outros casos.
fonte
O
size_t
tipo é definido como o tipo integral não assinado dosizeof
operador. No mundo real, você veráint
definido como 32 bits (para compatibilidade com versões anteriores), massize_t
definido como 64 bits (para poder declarar matrizes e estruturas com mais de 4 GiB de tamanho) em plataformas de 64 bits. Se along int
também tiver 64 bits, isso é chamado de convenção LP64; selong int
tiver 32 bits,long long int
e os ponteiros tiverem 64 bits, é LLP64. Você também pode obter o inverso, um programa que usa instruções de 64 bits para velocidade, mas ponteiros de 32 bits para economizar memória. Além disso,int
está assinado esize_t
não está assinado.Historicamente, havia várias outras plataformas em que os endereços eram maiores ou menores que o tamanho nativo de
int
. De fato, nos anos 70 e início dos anos 80, isso era mais comum do que não: todos os microcomputadores populares de 8 bits tinham registradores e endereços de 16 bits e a transição entre 16 e 32 bits também produziu muitas máquinas que tinham endereços mais amplos que seus registros. Ocasionalmente, ainda vejo perguntas aqui sobre o Borland Turbo C para MS-DOS, cujo modo de memória Enorme tinha endereços de 20 bits armazenados em 32 bits em uma CPU de 16 bits (mas que suportava o conjunto de instruções de 32 bits do 80386); o Motorola 68000 tinha uma ALU de 16 bits com registros e endereços de 32 bits; havia mainframes da IBM com endereços de 15, 24 ou 31 bits. Você também vê diferentes tamanhos de ALU e de barramento de endereços em sistemas incorporados.Quando o tempo
int
é menorsize_t
e você tenta armazenar o tamanho ou deslocamento de um arquivo ou objeto muito grande em umunsigned int
, existe a possibilidade de que ele possa estourar e causar um bug. Com umint
, há também a possibilidade de obter um número negativo. Se umint
ouunsigned int
for maior, o programa será executado corretamente, mas desperdiçará memória.Geralmente, você deve usar o tipo correto para esse fim, se quiser portabilidade. Muitas pessoas recomendam que você use matemática assinada em vez de não assinada (para evitar erros sutis e desagradáveis
1U < -3
). Para o efeito, os define biblioteca padrãoptrdiff_t
em<stddef.h>
como o tipo assinada do resultado da subtração um ponteiro de outro.Dito isso, uma solução alternativa pode ser verificar os limites de todos os endereços e compensações contra
INT_MAX
e /0
ouINT_MIN
conforme apropriado e ativar os avisos do compilador sobre a comparação de quantidades assinadas e não assinadas, caso você perca alguma. Você deve sempre, sempre, sempre verificar os acessos de sua matriz quanto a estouro em C de qualquer maneira.fonte
É porque size_t pode ser outra coisa senão um int (talvez uma estrutura). A idéia é que desacopla seu trabalho do tipo subjacente.
fonte
size_t
é especificado como um tipo inteiro não assinado . C11 §6.5.3.4 5 "O valor do resultado de ambos os operadores (sizeof
_Alignof
) é definido pela implementação e seu tipo (um tipo inteiro não assinado) ésize_t
".A definição de
SIZE_T
é encontrada em: https://msdn.microsoft.com/en-us/library/cc441980.aspx e https://msdn.microsoft.com/en-us/library/cc230394.aspxColando aqui as informações necessárias:
SIZE_T
é umULONG_PTR
número máximo de bytes para o qual um ponteiro pode apontar.Este tipo é declarado da seguinte maneira:
A
ULONG_PTR
é um tipo longo não assinado usado para precisão do ponteiro. É usado ao converter um ponteiro para um tipo longo para executar a aritmética do ponteiro.Este tipo é declarado da seguinte maneira:
fonte
SIZE_T
não ésize_t
, o que o OP perguntou.SIZE_T
é totalmente diferente desize_t
. Você não pode declarar uma variável do tipoSIZE_T
.