Se essas são suas únicas opções, use intse some_sizeestiver assinado, size_tse não estiver assinado.
Nate
8
@ Nate Isso está incorreto. O POSIX tem um tipo ssize_t, mas o tipo realmente correto a ser usado é ptrdiff_t.
Steven Stewart-Gallus
2
As respostas não são tão claras quanto na programação de baixo nível: C, montagem e execução de programas no Intel® 64 . Conforme declarado no livro, o uso de um índice int ipode não ser suficiente para lidar com uma grande variedade. Portanto, usando size_t ivocê pode endereçar mais índices, mesmo que você tenha uma grande variedade que não deve ser um problema. size_té um tipo de dados: geralmente um, unsigned long intmas isso depende do seu sistema.
De acordo com a norma ISO C de 1999 (C99), size_té um tipo inteiro não assinado de pelo menos 16 bits (consulte as seções 7.17 e 7.18.3).
size_té um tipo de dados não assinado definido por vários padrões C / C ++, por exemplo, o padrão C99 ISO / IEC 9899, definido em stddef.h. 1 Pode ser importado ainda mais pela inclusão de
stdlib.hcomo este arquivo inclui internamente stddef.h.
Este tipo é usado para representar o tamanho de um objeto. As funções de biblioteca que aceitam ou retornam tamanhos esperam que sejam do tipo ou tenham o tipo de retorno size_t. Além disso, o tamanho do operador baseado em compilador usado com mais freqüência deve ser avaliado como um valor constante compatível com
size_t.
Como implicação, size_té um tipo garantido para manter qualquer índice de matriz.
"Funções de biblioteca que aceitam ou retornam tamanhos esperam que sejam do tipo ... size_t" Exceto que stat () usa off_t para o tamanho de um arquivo
Draemon
64
@ Demra Esse comentário reflete uma confusão fundamental. size_té para objetos na memória. O padrão C nem sequer define stat()ou off_t(essas são definições POSIX) ou nada a ver com discos ou sistemas de arquivos - ele se interrompe nos FILEfluxos. O gerenciamento de memória virtual é completamente diferente dos sistemas de arquivos e do gerenciamento de arquivos no que diz respeito aos requisitos de tamanho, portanto, mencionar off_té irrelevante aqui.
jw013
3
@ jw013: Eu dificilmente chamaria isso de confusão fundamental, mas você faz uma observação interessante. Ainda assim, o texto citado não diz "tamanhos de objetos na memória" e "deslocamento" dificilmente é um bom nome para um tipo de tamanho, independentemente de onde ele esteja armazenado.
Draemon
30
@Draemon Bom ponto. Esta resposta cita a Wikipedia, que neste caso não tem a melhor explicação, na minha opinião. O padrão C em si é muito mais claro: define size_tcomo o tipo do resultado do sizeofoperador (cerca de 7,17p2 <stddef.h>). A Seção 6.5 explica exatamente como as expressões C funcionam (6.5.3.4 para sizeof). Como você não pode aplicar sizeofa um arquivo de disco (principalmente porque C nem define como funcionam os discos e os arquivos), não há espaço para confusão. Em outras palavras, culpe a Wikipedia (e esta resposta por citar a Wikipedia e não o padrão C real).
jw013
2
@ Demra - Eu também concordo com a avaliação da "confusão fundamental". Se você não leu os padrões C / C ++, pode pensar que "objeto" se refere a "programação orientada a objetos", o que não acontece. Leia o padrão C, que não possui nenhum desses objetos OOP, mas ainda possui objetos, e descubra. A resposta pode te surpreender!
Heath Hunnicutt
220
size_té um tipo não assinado. Portanto, não pode representar valores negativos (<0). Você o usa quando está contando algo e tem certeza de que não pode ser negativo. Por exemplo, strlen()retorna a size_tporque o comprimento de uma string deve ser pelo menos 0.
No seu exemplo, se seu índice de loop sempre for maior que 0, pode fazer sentido usar size_tou qualquer outro tipo de dados não assinado.
Ao usar um size_tobjeto, você deve garantir que, em todos os contextos em que ele é usado, incluindo aritmética, deseja valores não negativos. Por exemplo, digamos que você tenha:
e você deseja encontrar a diferença dos comprimentos de str2e str1. Você não pode fazer:
int diff = s2 - s1;/* bad */
Isso ocorre porque o valor atribuído diffsempre será um número positivo, mesmo quando s2 < s1, porque o cálculo é feito com tipos não assinados. Nesse caso, dependendo do seu caso de uso, é melhor usar int(ou long long) para s1e s2.
Existem algumas funções no C / POSIX que podem / devem usar size_t, mas não por motivos históricos. Por exemplo, o segundo parâmetro para fgetsideal deve ser size_t, mas é int.
@Alok: Duas perguntas: 1) qual é o tamanho size_t? 2) por que devo preferir size_talgo assim unsigned int?
Lazer
2
@ Lazer: o tamanho de size_té sizeof(size_t). O padrão C garante que SIZE_MAXserá pelo menos 65535. size_té o tipo retornado pelo sizeofoperador e é usado na biblioteca padrão (por exemplo, strlenretornos size_t). Como disse Brendan, size_tnão precisa ser o mesmo que unsigned int.
Alok Singhal
4
@Lazer - sim, size_té garantido que seja um tipo não assinado.
Alok Singhal
2
@ Celeritas não, quero dizer que um tipo não assinado pode representar apenas valores não negativos. Eu provavelmente deveria ter dito "Não pode representar valores negativos".
Alok Singhal
4
@JasonOster, o complemento de dois não é um requisito no padrão C. Se o valor de s2 - s1estourar um int, o comportamento é indefinido.
Alok Singhal
73
size_t é um tipo que pode conter qualquer índice de matriz.
Dependendo da implementação, pode ser um dos seguintes:
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
Veja como size_té definido na stddef.hminha máquina:
Certamente typedef unsigned long size_tdepende do compilador. Ou você está sugerindo que é sempre assim?
chux - Restabelece Monica
4
@chux: De fato, apenas porque uma implementação a define como tal, não significa que todos o fazem. Caso em questão: Windows de 64 bits. unsigned longé de 32 bits, size_té de 64 bits.
Tim Čas
2
qual é o propósito de size_t exatamente? Quando eu posso criar uma variável para mim como: "int mysize_t;" ou "long mysize_t" ou "long mysize_t não assinado". Por que alguém deveria ter criado essa variável para mim?
midkin 31/07
1
@midkin size_tnão é uma variável. É um tipo que você pode usar quando quiser representar o tamanho de um objeto na memória.
Arjun Sreedharan
1
é verdade que size_tsempre há 32 bits na máquina de 32 bits e 64 bits da mesma forma?
Eu tenho o mesmo ambiente, no entanto, eu testei por 32 bits, passando a opção "-m32" do GCC, o resultado foi: "typedef unsigned int size_t". Obrigado por compartilhar este comando incrível @Ciro, isso me ajudou muito! :-)
silvioprog 21/03
2
O assunto em si não é confuso. É a mente confusa que tenta fazer muitas perguntas e dar muitas respostas. Surpreende-me que esta resposta e a de Arjun Sreedharan ainda não impeçam as pessoas de perguntar e responder.
biocyberman
1
Ótima resposta, porque na verdade diz o que size_té , pelo menos em uma distribuição Linux popular.
Como ninguém ainda o mencionou, a principal significância linguística de size_té que o sizeofoperador retorna um valor desse tipo. Da mesma forma, o significado primário de ptrdiff_té que subtrair um ponteiro de outro produzirá um valor desse tipo. As funções de biblioteca que o aceitam fazem isso porque permitirão que essas funções funcionem com objetos cujo tamanho exceda UINT_MAX em sistemas onde esses objetos possam existir, sem forçar os chamadores a desperdiçarem o código que passa um valor maior que "int não assinado" em sistemas onde o tipo maior seria suficiente para todos os objetos possíveis.
Minha pergunta sempre foi: se sizeof nunca existisse, haveria necessidade de size_t?
decano P
@ DeanP: Talvez não, embora houvesse uma pergunta de que tipo de argumento deve ser usado para coisas como malloc(). Pessoalmente, eu gostaria de ter visto versões que aceitam argumentos do tipo int, longe long long, com algumas implementações promovendo tipos mais curtos e outras implementando, por exemplo, lmalloc(long n) {return (n < 0 || n > 32767) ? 0 : imalloc(n);}[em algumas plataformas, chamar imalloc(123)seria mais barato do que chamar lmalloc(123);, e até mesmo em uma plataforma onde size_t16 pedaços, código que quer alocar tamanho calculado em um `valor long` ...
supercat
... deve poder contar com a falha na alocação se o valor for maior do que o alocador pode suportar.
Supercat
11
Para explicar por que é size_tnecessário existir e como chegamos aqui:
Em termos pragmáticos, size_te ptrdiff_tsão garantidos para ser 64 bits de largura em uma implementação de 64 bits, 32 bits de largura em uma implementação de 32 bits, e assim por diante. Eles não podiam forçar nenhum tipo existente a significar isso, em todos os compiladores, sem quebrar o código legado.
Um size_tou ptrdiff_tnão é necessariamente o mesmo que um intptr_tou uintptr_t. Eles eram diferentes em algumas arquiteturas que ainda estavam em uso quando size_te ptrdiff_tforam adicionados ao padrão no final dos anos 80, e tornando-se obsoleto quando C99 acrescentou muitos novos tipos, mas ainda não passaram (como Windows de 16 bits). O x86 no modo protegido de 16 bits tinha uma memória segmentada em que a maior matriz ou estrutura possível podia ter apenas 65.536 bytes de tamanho, mas um farponteiro precisava ter 32 bits de largura, mais largo que os registros. Nesses, intptr_tteria 32 bits de largura, mas size_teptrdiff_tpode ter 16 bits de largura e caber em um registro. E quem sabia que tipo de sistema operacional poderia ser escrito no futuro? Em teoria, a arquitetura i386 oferece um modelo de segmentação de 32 bits com ponteiros de 48 bits que nenhum sistema operacional jamais usou.
O tipo de deslocamento de memória não pode ser longporque muito código legado supõe que longseja exatamente 32 bits de largura. Essa suposição foi incorporada às APIs do UNIX e do Windows. Infelizmente, muitos outros códigos herdados também assumiram que a longé grande o suficiente para conter um ponteiro, um deslocamento de arquivo, o número de segundos decorridos desde 1970 e assim por diante. O POSIX agora fornece uma maneira padronizada de forçar a última suposição a ser verdadeira, em vez da anterior, mas nenhuma é uma suposição portátil a ser feita.
Não poderia ser intporque apenas um punhado de compiladores nos anos 90 tinham int64 bits de largura. Então eles realmente ficaram estranhos mantendo long32 bits de largura. A próxima revisão do Padrão declarou ilegal intque fosse maior do que long, mas intainda tem 32 bits de largura na maioria dos sistemas de 64 bits.
Não poderia ser long long int, o que de qualquer maneira foi adicionado mais tarde, pois foi criado para ter pelo menos 64 bits de largura, mesmo em sistemas de 32 bits.
Portanto, era necessário um novo tipo. Mesmo que não fosse, todos esses outros tipos significavam algo diferente de um deslocamento dentro de uma matriz ou objeto. E se houvesse uma lição do fiasco da migração de 32 para 64 bits, seria específico sobre quais propriedades um tipo precisava ter, e não usar uma que significasse coisas diferentes em programas diferentes.
Não concorde com " size_te tenha a ptrdiff_tgarantia de ter 64 bits de largura em uma implementação de 64 bits" etc. A garantia é exagerada. O intervalo de size_té impulsionado principalmente pela capacidade de memória da implementação. "uma implementação de n bits" é principalmente a largura nativa do processador de números inteiros. Certamente muitas implementações usam um tamanho de memória e largura de barramento de processador semelhantes, mas existem inteiros nativos amplos com memória insuficiente ou processadores estreitos com muita memória e separam essas duas propriedades de implementação.
chux - Restabelece Monica em 23/01
8
size_te intnão são intercambiáveis. Por exemplo, no Linux de size_t64 bits, o tamanho é de 64 bits (ou seja sizeof(void*)), mas inté de 32 bits.
Observe também que size_tnão está assinado. Se você precisar de uma versão assinada, existe ssize_tem algumas plataformas e isso seria mais relevante para o seu exemplo.
Como regra geral, eu sugeriria o uso intpara a maioria dos casos gerais e somente o uso size_t/ ssize_tquando houver uma necessidade específica (com, mmap()por exemplo).
Em geral, se você está começando em 0 e subindo, sempre use um tipo não assinado para evitar um estouro levando você a uma situação de valor negativo. Isso é extremamente importante, porque se os limites de sua matriz forem inferiores ao máximo do seu loop, mas o loop máximo for superior ao máximo do seu tipo, você contornará negativo e poderá ocorrer uma falha de segmentação (SIGSEGV ) Portanto, em geral, nunca use int para um loop começando em 0 e subindo. Use um não assinado.
Não posso aceitar sua argumentação. Você diz que é melhor que o bug de estouro silenciosamente leve ao acesso a dados válidos em sua matriz?
MAF-soft
1
@ maf-soft está correto. se o erro não for detectado, será pior do que uma falha no programa. por que essa resposta foi votada?
yoyo_fun
Se ele acessar dados válidos em sua matriz, não será um erro, porque o tipo não assinado não excederá o limite do tipo assinado. O que é essa lógica pessoal? Digamos que, por algum motivo, você use char para iterar mais de 256 elementos do array ... assinado irá exceder em 127 e 128 o elemento será sigsegv, mas se você usar não assinado, ele passará por todo o array conforme o esperado. Então, novamente, quando você estiver usando um int, suas matrizes não vai ser muito maior do que 2 bilhões de elementos para que de qualquer forma não importa ...
roxo Ice
1
Não consigo imaginar nenhuma situação em que o excesso de número inteiro não seja um erro, seja positivo ou negativo. Só porque você não recebe um segfault não significa que você vê o comportamento correto! E você pode experimentar uma falha de segmentação, ou não, se seu deslocamento é positivo ou negativo; tudo depende do seu layout de memória. @ PurpleIce, não acho que você esteja dizendo a mesma coisa que esta resposta; seu argumento parece ser que você deve escolher um tipo de dados grande o suficiente para armazenar o maior valor que deseja inserir nele, o que é apenas senso comum.
Soren Bjornstad 01/04/19
Dito isto, prefiro usar um tipo não assinado para índices de loop semântica ; se sua variável nunca for negativa, você também pode indicar isso no tipo que escolher. Também poderia permitir que o compilador localizasse um bug em que o valor acabasse negativo, embora o GCC pelo menos seja bastante terrível em detectar esse erro específico (em uma ocasião eu inicializei um sem sinal para -1 e não recebi um aviso). Da mesma forma, um size_t é semanticamente apropriado para índices de matriz.
Soren Bjornstad 01/04/19
3
size_t é um tipo de dados inteiro não assinado. Nos sistemas que usam a GNU C Library, isso será int sem sinal ou int longo sem sinal. size_t é comumente usado para indexação de array e contagem de loop.
size_t ou qualquer tipo não assinado pode ser visto como variável de loop, pois as variáveis de loop geralmente são maiores ou iguais a 0.
Quando usamos um objeto size_t , precisamos garantir que, em todos os contextos em que ele é usado, incluindo aritmética, desejemos apenas valores não negativos. Por exemplo, o programa a seguir daria definitivamente o resultado inesperado:
// C program to demonstrate that size_t or// any unsigned int type should be used // carefully when used in a loop#include<stdio.h>int main(){constsize_t N =10;int a[N];// This is finefor(size_t n =0; n < N;++n)
a[n]= n;// But reverse cycles are tricky for unsigned // types as can lead to infinite loopfor(size_t n = N-1; n >=0;--n)
printf("%d ", a[n]);}OutputInfinite loop and then segmentation fault
size_té um tipo de dados inteiro não assinado que pode atribuir apenas 0 e valores maiores que 0. Ele mede bytes do tamanho de qualquer objeto e retorna pelo sizeofoperador.
consté a representação da sintaxe de size_t, mas sem constvocê pode executar o programa.
constsize_t number;
size_tusado regularmente para indexação de array e contagem de loop. Se o compilador é 32-bitque iria trabalhar unsigned int. Se o compilador é 64-bitque iria trabalhar unsigned long long inttambém. Existe para o tamanho máximo de size_tacordo com o tipo de compilador.
size_tjá definem no <stdio.h>arquivo de cabeçalho, mas também pode definir por
<stddef.h>, <stdlib.h>, <string.h>, <time.h>, <wchar.h>cabeçalhos.
Exemplo (com const)
#include<stdio.h>int main(){constsize_t value =200;size_t i;int arr[value];for(i =0; i < value ;++i){
arr[i]= i;}size_t size =sizeof(arr);
printf("size = %zu\n", size);}
Resultado -:size = 800
Exemplo (sem const)
#include<stdio.h>int main(){size_t value =200;size_t i;int arr[value];for(i =0; i < value ;++i){
arr[i]= i;}size_t size =sizeof(arr);
printf("size = %zu\n", size);}
Não é verdade. O tamanho do ponteiro pode ser maior que o size_t. Vários exemplos: compiladores C no modo real x86 podem ter 32 bits FARou HUGEponteiros, mas size_t ainda é 16 bits. Outro exemplo: o Watcom C costumava ter um ponteiro de gordura especial para memória estendida com 48 bits de largura, mas size_tnão tinha. No controlador incorporado com arquitetura Harvard, você também não tem correlação, porque ambos dizem respeito a diferentes espaços de endereço.
int
sesome_size
estiver assinado,size_t
se não estiver assinado.int i
pode não ser suficiente para lidar com uma grande variedade. Portanto, usandosize_t i
você pode endereçar mais índices, mesmo que você tenha uma grande variedade que não deve ser um problema.size_t
é um tipo de dados: geralmente um,unsigned long int
mas isso depende do seu sistema.Respostas:
Da Wikipedia :
Como implicação,
size_t
é um tipo garantido para manter qualquer índice de matriz.fonte
size_t
é para objetos na memória. O padrão C nem sequer definestat()
ouoff_t
(essas são definições POSIX) ou nada a ver com discos ou sistemas de arquivos - ele se interrompe nosFILE
fluxos. O gerenciamento de memória virtual é completamente diferente dos sistemas de arquivos e do gerenciamento de arquivos no que diz respeito aos requisitos de tamanho, portanto, mencionaroff_t
é irrelevante aqui.size_t
como o tipo do resultado dosizeof
operador (cerca de 7,17p2<stddef.h>
). A Seção 6.5 explica exatamente como as expressões C funcionam (6.5.3.4 parasizeof
). Como você não pode aplicarsizeof
a um arquivo de disco (principalmente porque C nem define como funcionam os discos e os arquivos), não há espaço para confusão. Em outras palavras, culpe a Wikipedia (e esta resposta por citar a Wikipedia e não o padrão C real).size_t
é um tipo não assinado. Portanto, não pode representar valores negativos (<0). Você o usa quando está contando algo e tem certeza de que não pode ser negativo. Por exemplo,strlen()
retorna asize_t
porque o comprimento de uma string deve ser pelo menos 0.No seu exemplo, se seu índice de loop sempre for maior que 0, pode fazer sentido usar
size_t
ou qualquer outro tipo de dados não assinado.Ao usar um
size_t
objeto, você deve garantir que, em todos os contextos em que ele é usado, incluindo aritmética, deseja valores não negativos. Por exemplo, digamos que você tenha:e você deseja encontrar a diferença dos comprimentos de
str2
estr1
. Você não pode fazer:Isso ocorre porque o valor atribuído
diff
sempre será um número positivo, mesmo quandos2 < s1
, porque o cálculo é feito com tipos não assinados. Nesse caso, dependendo do seu caso de uso, é melhor usarint
(oulong long
) paras1
es2
.Existem algumas funções no C / POSIX que podem / devem usar
size_t
, mas não por motivos históricos. Por exemplo, o segundo parâmetro parafgets
ideal deve sersize_t
, mas éint
.fonte
size_t
? 2) por que devo preferirsize_t
algo assimunsigned int
?size_t
ésizeof(size_t)
. O padrão C garante queSIZE_MAX
será pelo menos 65535.size_t
é o tipo retornado pelosizeof
operador e é usado na biblioteca padrão (por exemplo,strlen
retornossize_t
). Como disse Brendan,size_t
não precisa ser o mesmo queunsigned int
.size_t
é garantido que seja um tipo não assinado.s2 - s1
estourar umint
, o comportamento é indefinido.size_t
é um tipo que pode conter qualquer índice de matriz.Dependendo da implementação, pode ser um dos seguintes:
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
Veja como
size_t
é definido nastddef.h
minha máquina:fonte
typedef unsigned long size_t
depende do compilador. Ou você está sugerindo que é sempre assim?unsigned long
é de 32 bits,size_t
é de 64 bits.size_t
não é uma variável. É um tipo que você pode usar quando quiser representar o tamanho de um objeto na memória.size_t
sempre há 32 bits na máquina de 32 bits e 64 bits da mesma forma?Se você é do tipo empírico ,
Saída para o Ubuntu 14.04 GCC 4.8 de 64 bits:
Observe que
stddef.h
é fornecido pelo GCC e não glibcsrc/gcc/ginclude/stddef.h
no GCC 4.2.Aparições C99 interessantes
malloc
tomasize_t
como argumento, portanto, determina o tamanho máximo que pode ser alocado.E como também é retornado por
sizeof
, acho que limita o tamanho máximo de qualquer matriz.Consulte também: Qual é o tamanho máximo de uma matriz em C?
fonte
size_t
é , pelo menos em uma distribuição Linux popular.A página de manual do types.h diz:
fonte
Como ninguém ainda o mencionou, a principal significância linguística de
size_t
é que osizeof
operador retorna um valor desse tipo. Da mesma forma, o significado primário deptrdiff_t
é que subtrair um ponteiro de outro produzirá um valor desse tipo. As funções de biblioteca que o aceitam fazem isso porque permitirão que essas funções funcionem com objetos cujo tamanho exceda UINT_MAX em sistemas onde esses objetos possam existir, sem forçar os chamadores a desperdiçarem o código que passa um valor maior que "int não assinado" em sistemas onde o tipo maior seria suficiente para todos os objetos possíveis.fonte
malloc()
. Pessoalmente, eu gostaria de ter visto versões que aceitam argumentos do tipoint
,long
elong long
, com algumas implementações promovendo tipos mais curtos e outras implementando, por exemplo,lmalloc(long n) {return (n < 0 || n > 32767) ? 0 : imalloc(n);}
[em algumas plataformas, chamarimalloc(123)
seria mais barato do que chamarlmalloc(123);
, e até mesmo em uma plataforma ondesize_t
16 pedaços, código que quer alocar tamanho calculado em um `valor long` ...Para explicar por que é
size_t
necessário existir e como chegamos aqui:Em termos pragmáticos,
size_t
eptrdiff_t
são garantidos para ser 64 bits de largura em uma implementação de 64 bits, 32 bits de largura em uma implementação de 32 bits, e assim por diante. Eles não podiam forçar nenhum tipo existente a significar isso, em todos os compiladores, sem quebrar o código legado.Um
size_t
ouptrdiff_t
não é necessariamente o mesmo que umintptr_t
ouuintptr_t
. Eles eram diferentes em algumas arquiteturas que ainda estavam em uso quandosize_t
eptrdiff_t
foram adicionados ao padrão no final dos anos 80, e tornando-se obsoleto quando C99 acrescentou muitos novos tipos, mas ainda não passaram (como Windows de 16 bits). O x86 no modo protegido de 16 bits tinha uma memória segmentada em que a maior matriz ou estrutura possível podia ter apenas 65.536 bytes de tamanho, mas umfar
ponteiro precisava ter 32 bits de largura, mais largo que os registros. Nesses,intptr_t
teria 32 bits de largura, massize_t
eptrdiff_t
pode ter 16 bits de largura e caber em um registro. E quem sabia que tipo de sistema operacional poderia ser escrito no futuro? Em teoria, a arquitetura i386 oferece um modelo de segmentação de 32 bits com ponteiros de 48 bits que nenhum sistema operacional jamais usou.O tipo de deslocamento de memória não pode ser
long
porque muito código legado supõe quelong
seja exatamente 32 bits de largura. Essa suposição foi incorporada às APIs do UNIX e do Windows. Infelizmente, muitos outros códigos herdados também assumiram que along
é grande o suficiente para conter um ponteiro, um deslocamento de arquivo, o número de segundos decorridos desde 1970 e assim por diante. O POSIX agora fornece uma maneira padronizada de forçar a última suposição a ser verdadeira, em vez da anterior, mas nenhuma é uma suposição portátil a ser feita.Não poderia ser
int
porque apenas um punhado de compiladores nos anos 90 tinhamint
64 bits de largura. Então eles realmente ficaram estranhos mantendolong
32 bits de largura. A próxima revisão do Padrão declarou ilegalint
que fosse maior do quelong
, masint
ainda tem 32 bits de largura na maioria dos sistemas de 64 bits.Não poderia ser
long long int
, o que de qualquer maneira foi adicionado mais tarde, pois foi criado para ter pelo menos 64 bits de largura, mesmo em sistemas de 32 bits.Portanto, era necessário um novo tipo. Mesmo que não fosse, todos esses outros tipos significavam algo diferente de um deslocamento dentro de uma matriz ou objeto. E se houvesse uma lição do fiasco da migração de 32 para 64 bits, seria específico sobre quais propriedades um tipo precisava ter, e não usar uma que significasse coisas diferentes em programas diferentes.
fonte
size_t
e tenha aptrdiff_t
garantia de ter 64 bits de largura em uma implementação de 64 bits" etc. A garantia é exagerada. O intervalo desize_t
é impulsionado principalmente pela capacidade de memória da implementação. "uma implementação de n bits" é principalmente a largura nativa do processador de números inteiros. Certamente muitas implementações usam um tamanho de memória e largura de barramento de processador semelhantes, mas existem inteiros nativos amplos com memória insuficiente ou processadores estreitos com muita memória e separam essas duas propriedades de implementação.size_t
eint
não são intercambiáveis. Por exemplo, no Linux desize_t
64 bits, o tamanho é de 64 bits (ou sejasizeof(void*)
), masint
é de 32 bits.Observe também que
size_t
não está assinado. Se você precisar de uma versão assinada, existessize_t
em algumas plataformas e isso seria mais relevante para o seu exemplo.Como regra geral, eu sugeriria o uso
int
para a maioria dos casos gerais e somente o usosize_t
/ssize_t
quando houver uma necessidade específica (com,mmap()
por exemplo).fonte
Em geral, se você está começando em 0 e subindo, sempre use um tipo não assinado para evitar um estouro levando você a uma situação de valor negativo. Isso é extremamente importante, porque se os limites de sua matriz forem inferiores ao máximo do seu loop, mas o loop máximo for superior ao máximo do seu tipo, você contornará negativo e poderá ocorrer uma falha de segmentação (SIGSEGV ) Portanto, em geral, nunca use int para um loop começando em 0 e subindo. Use um não assinado.
fonte
size_t é um tipo de dados inteiro não assinado. Nos sistemas que usam a GNU C Library, isso será int sem sinal ou int longo sem sinal. size_t é comumente usado para indexação de array e contagem de loop.
fonte
size_t ou qualquer tipo não assinado pode ser visto como variável de loop, pois as variáveis de loop geralmente são maiores ou iguais a 0.
Quando usamos um objeto size_t , precisamos garantir que, em todos os contextos em que ele é usado, incluindo aritmética, desejemos apenas valores não negativos. Por exemplo, o programa a seguir daria definitivamente o resultado inesperado:
fonte
size_t
é um tipo de dados inteiro não assinado que pode atribuir apenas 0 e valores maiores que 0. Ele mede bytes do tamanho de qualquer objeto e retorna pelosizeof
operador.const
é a representação da sintaxe desize_t
, mas semconst
você pode executar o programa.size_t
usado regularmente para indexação de array e contagem de loop. Se o compilador é32-bit
que iria trabalharunsigned int
. Se o compilador é64-bit
que iria trabalharunsigned long long int
também. Existe para o tamanho máximo desize_t
acordo com o tipo de compilador.size_t
já definem no<stdio.h>
arquivo de cabeçalho, mas também pode definir por<stddef.h>
,<stdlib.h>
,<string.h>
,<time.h>
,<wchar.h>
cabeçalhos.const
)Resultado -:
size = 800
const
)Resultado -:
size = 800
fonte
Do meu entendimento,
size_t
é umunsigned
número inteiro cujo tamanho de bit é grande o suficiente para armazenar um ponteiro da arquitetura nativa.Assim:
fonte
size_t
. Vários exemplos: compiladores C no modo real x86 podem ter 32 bitsFAR
ouHUGE
ponteiros, mas size_t ainda é 16 bits. Outro exemplo: o Watcom C costumava ter um ponteiro de gordura especial para memória estendida com 48 bits de largura, massize_t
não tinha. No controlador incorporado com arquitetura Harvard, você também não tem correlação, porque ambos dizem respeito a diferentes espaços de endereço.size_t