O size_t
tipo é o tipo inteiro não assinado que é o resultado do sizeof
operador (e do offsetof
operador); portanto, é garantido que seja grande o suficiente para conter o tamanho do maior objeto que seu sistema pode manipular (por exemplo, uma matriz estática de 8 GB).
O size_t
tipo pode ser maior que, igual a ou menor que um unsigned int
, e seu compilador pode fazer suposições sobre isso para otimização.
Você pode encontrar informações mais precisas no padrão C99, seção 7.17, cujo rascunho está disponível na Internet em formato pdf , ou no padrão C11, seção 7.19, também disponível como rascunho em pdf .
size_t
podem representar! Se não, quem faz?O clássico C (o dialeto inicial de C descrito por Brian Kernighan e Dennis Ritchie em The C Programming Language, Prentice-Hall, 1978) não forneceu
size_t
. O comitê de padrões C apresentadosize_t
para eliminar um problema de portabilidadeExplicado em detalhes no site incorporado.com (com um exemplo muito bom)
fonte
Em resumo,
size_t
nunca é negativo e maximiza o desempenho porque é typedef para ser o tipo inteiro não assinado que é grande o suficiente - mas não muito grande - para representar o tamanho do maior objeto possível na plataforma de destino.Os tamanhos nunca devem ser negativos e, de fato,
size_t
são do tipo não assinado. Além disso, comosize_t
não é assinado, é possível armazenar números aproximadamente duas vezes maiores que o tipo assinado correspondente, porque podemos usar o bit de sinal para representar a magnitude, como todos os outros bits do número inteiro não assinado. Quando ganhamos mais um bit, multiplicamos o intervalo de números que podemos representar por um fator de cerca de dois.Então, você pergunta, por que não usar apenas um
unsigned int
? Pode não ser capaz de armazenar números grandes o suficiente. Em uma implementação comunsigned int
32 bits, o maior número que pode representar é4294967295
. Alguns processadores, como o IP16L32, podem copiar objetos maiores que4294967295
bytes.Então, você pergunta, por que não usar um
unsigned long int
? Exige um pedágio de desempenho em algumas plataformas. O padrão C exige que umlong
ocupe pelo menos 32 bits. Uma plataforma IP16L32 implementa cada comprimento de 32 bits como um par de palavras de 16 bits. Quase todos os operadores de 32 bits nessas plataformas exigem duas instruções, se não mais, porque trabalham com os 32 bits em dois pedaços de 16 bits. Por exemplo, mover um comprimento de 32 bits geralmente requer duas instruções da máquina - uma para mover cada pedaço de 16 bits.O uso
size_t
evita esse custo de desempenho. De acordo com este artigo fantástico , "Typesize_t
é um typedef que é um apelido para algum tipo de número inteiro não assinado, normalmenteunsigned int
ouunsigned long
, mas possivelmente atéunsigned long long
. Cada implementação do Standard C deve escolher o número inteiro não assinado que é grande o suficiente - mas não maior que o necessário - para representar o tamanho do maior objeto possível na plataforma de destino ".fonte
unsigned int
lata e varia de um sistema para outro. É necessário que seja pelo menos65536
, mas é comum4294967295
e pode ser18446744073709551615
(2 ** 64-1) em alguns sistemas.unsigned char
). O padrão parece não conter a string '65535' ou '65536' em qualquer lugar e '+32767' ocorre apenas (1,9: 9) em uma nota como o maior número possível de números inteiro representávelint
; nenhuma garantia é dada, mesmo queINT_MAX
não possa ser menor que isso!O tipo size_t é o tipo retornado pelo operador sizeof. É um número inteiro não assinado capaz de expressar o tamanho em bytes de qualquer intervalo de memória suportado na máquina host. É (normalmente) relacionado a ptrdiff_t, em que ptrdiff_t é um valor inteiro assinado, de modo que sizeof (ptrdiff_t) e sizeof (size_t) sejam iguais.
Ao escrever o código C, você sempre deve usar size_t sempre que lidar com intervalos de memória.
O tipo int, por outro lado, é basicamente definido como o tamanho do valor inteiro (assinado) que a máquina host pode usar para executar com eficiência a aritmética inteira. Por exemplo, em muitos computadores mais antigos do tipo PC, o valor sizeof (size_t) seria 4 (bytes), mas sizeof (int) seria 2 (byte). A aritmética de 16 bits era mais rápida que a aritmética de 32 bits, embora a CPU pudesse lidar com um espaço de memória (lógico) de até 4 GiB.
Use o tipo int somente quando você se preocupa com a eficiência, pois sua precisão real depende muito das opções do compilador e da arquitetura da máquina. Em particular, o padrão C especifica os seguintes invariantes: sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long) não colocando outras limitações na representação real da precisão disponível ao programador para cada um dos esses tipos primitivos.
Nota: NÃO é o mesmo que em Java (que realmente especifica a precisão de bits para cada um dos tipos 'char', 'byte', 'short', 'int' e 'long').
fonte
size_t
é capaz de representar o tamanho de qualquer objeto único (por exemplo: número, matriz, estrutura). Todo o intervalo de memória pode excedersize_t
size_t
- espero que você não esteja falando sério. Na maioria das vezes, não lidamos com matrizes em que a cardinalidade do espaço de endereço + portabilidade é importante. Nesses casos, você aceitariasize_t
. Nos demais casos, você obtém índices de números inteiros (assinados). Como a confusão (que ocorre sem aviso prévio) decorrente do comportamento inesperado de sub-fluxo de assinaturas é mais comum e pior que os problemas de portabilidade que podem surgir nos outros casos.Digite size_t deve ser grande o suficiente para armazenar o tamanho de qualquer objeto possível. Int não assinado não precisa atender a essa condição.
Por exemplo, nos sistemas de 64 bits, int e unsigned int podem ter 32 bits de largura, mas size_t deve ser grande o suficiente para armazenar números maiores que 4G
fonte
size_t
que só teria que ser tão grande se o compilador pudesse aceitar um tipo X tal que sizeof (X) renderia um valor maior que 4G. A maioria dos compiladores rejeitariatypedef unsigned char foo[1000000000000LL][1000000000000LL]
, por exemplo , efoo[65536][65536];
poderia mesmo ser legitimamente rejeitada se excedesse um limite definido pela implementação documentado.Este trecho do manual glibc 0.02 também pode ser relevante ao pesquisar o tópico:
Há um problema em potencial com o tipo size_t e as versões do GCC anteriores à liberação 2.4. O ANSI C exige que size_t sempre seja um tipo não assinado. Para compatibilidade com os arquivos de cabeçalho dos sistemas existentes, o GCC define size_t em
stddef.h' to be whatever type the system's
sys / types.h 'como ele é. A maioria dos sistemas Unix que definem size_t em `sys / types.h ', definem como um tipo assinado. Algum código na biblioteca depende do tamanho_t ser um tipo não assinado e não funcionará corretamente se estiver assinado.O código da biblioteca GNU C que espera que size_t não seja assinado está correto. A definição de size_t como um tipo assinado está incorreta. Planejamos que na versão 2.4, o GCC sempre defina size_t como um tipo não assinado e o
fixincludes' script will massage the system's
sys / types.h 'para não entrar em conflito com isso.Enquanto isso, resolvemos esse problema dizendo ao GCC explicitamente para usar um tipo não assinado para size_t ao compilar a biblioteca GNU C. O `configure 'detectará automaticamente o tipo que o GCC usa para size_t organizar para substituí-lo, se necessário.
fonte
Se meu compilador estiver definido como 32 bits,
size_t
não será outro senão um typedef paraunsigned int
. Se meu compilador estiver definido como 64 bits,size_t
nada mais será do que um typedef paraunsigned long long
.fonte
unsigned long
para os dois casos em alguns sistemas operacionais.size_t é o tamanho de um ponteiro.
Portanto, em 32 bits ou no modelo comum ILP32 (inteiro, longo, ponteiro) size_t é 32 bits. e em 64 bits ou no modelo LP64 (longo, ponteiro) comum size_t é de 64 bits (números inteiros ainda são 32 bits).
Existem outros modelos, mas esses são os que o g ++ usa (pelo menos por padrão)
fonte
size_t
não é necessariamente do mesmo tamanho que um ponteiro, embora geralmente seja. Um ponteiro deve ser capaz de apontar para qualquer local na memória;size_t
só precisa ser grande o suficiente para representar o tamanho do maior objeto único.