Em vários exemplos de C ++, vejo um uso do tipo em size_tque eu teria usado um simples int. Qual a diferença e por que size_tdeveria ser melhor?
Em vários exemplos de C ++, vejo um uso do tipo em size_tque eu teria usado um simples int. Qual a diferença e por que size_tdeveria ser melhor?
Respostas:
Da amigável Wikipedia :
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.
Além disso, verifique Por que o size_t é importante
/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.
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.
É porque size_t pode ser outra coisa senão um int (talvez uma estrutura). A idéia é que desacopla seu trabalho do tipo subjacente.
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.aspx
Colando aqui as informações necessárias:
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.
Este tipo é declarado da seguinte maneira:
typedef unsigned __int3264 ULONG_PTR;
SIZE_Tnão é size_t, o que o OP perguntou.
SIZE_Té totalmente diferente de size_t. Você não pode declarar uma variável do tipo SIZE_T.