Qual é a diferença entre size_t e int em C ++?


173

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?


3
Para um exemplo real onde eles não são intercambiáveis, consulte a pergunta que fiz anteriormente: stackoverflow.com/questions/645168/...
Tyler McHenry

Respostas:


153

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


76
E então, o que é size_t?
NDEthos

8
@ 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.


12

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.


8

É porque size_t pode ser outra coisa senão um int (talvez uma estrutura). A idéia é que desacopla seu trabalho do tipo subjacente.


8
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".
chux - Restabelece Monica 07/07

-1

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;

2
SIZE_Tnão é size_t, o que o OP perguntou.
Ikegami #

2
Essa é uma extensão da Microsoft, não faz parte do idioma padrão.
Davislor

SIZE_Té totalmente diferente de size_t. Você não pode declarar uma variável do tipo SIZE_T.
Calocedrus
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.