Onde encontro a definição de size_t?

123

Vejo variáveis ​​definidas com esse tipo, mas não sei de onde elas vêm, nem qual é seu objetivo. Por que não usar int ou unsigned int? (E quanto a outros tipos "semelhantes"? Void_t, etc).

Eliseo Ocampos
fonte
Pergunta exata: stackoverflow.com/questions/502856/…
kjfletch
@kjfletch: hhhmmm, é estranho que procurar pelo termo 'size_t' (como eu fiz anteriormente) não retorne essa pergunta.
Eliseo Ocampos
1
@Eliseo - A função de busca do Stackoverflow é péssima. Use o Google com um parâmetro 'site: stackoverflow.com'.
22711 Michael Burr
8
O OP perguntou especificamente Onde encontro a definição de size_t? Eu cheguei aqui procurando a mesma coisa. O dup citado não discute onde encontrar a declaração.
jww 27/07
9
Obviamente, essa pergunta não é a mesma que a vinculada. "Onde encontro alguma coisa" não é a mesma coisa que "Qual é a diferença entre" (mesmo que a resposta de uma forneça a resposta para a outra). Minha pesquisa no Google por 'c ++ onde está a definição size_t' me levou diretamente aqui, e eu teria perdido a outra pergunta, porque é diferente .
Dan Nissenbaum 22/11

Respostas:

122

Da Wikipedia

Os arquivos stdlib.he stddef.hheader definem um tipo de dados chamado size_t1, que é usado para representar o tamanho de um objeto. As funções de biblioteca que aceitam tamanhos esperam que sejam do tipo size_te o operador sizeof avalia comosize_t .

O tipo real de size_tdepende 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, 2 especialmente quando as arquiteturas de 64 bits se tornam mais prevalentes.

Desde C99 7.17.1 / 2

Os seguintes tipos e macros são definidos no cabeçalho padrão stddef.h

<snip>

size_t

que é o tipo inteiro não assinado do resultado do operador sizeof

Martin Liversage
fonte
2
Por exemplo, no Win64, inte os unsigned inttipos são 32 bits, enquanto size_t é 64 bits.
227 Michael Burr
7
Por favor consulte a norma ISO C (99) (a partir do qual o padrão C ++ inclui) secções 7,17 e 7.18.3
Martin Iorque
3
@LokiAstari, por que você simplesmente não edita a resposta, pois sabe onde está escrita na norma?
Hi-Angel
Então, onde está a resposta C ++?
Lothar
@ Lothar Acho que a única diferença é que size_t pode ser uma palavra-chave e, caso contrário, tem o mesmo significado.
Paul Stelian
30

De acordo com size_t, a descrição em pt.cppreference.com size_t é definida nos seguintes cabeçalhos:

std::size_t

...    

Defined in header <cstddef>         
Defined in header <cstdio>      
Defined in header <cstring>         
Defined in header <ctime>       
Defined in header <cwchar>
stefanB
fonte
2
Isso é exatamente o que eu precisava, essa resposta deve ser votada.
Neodefi
27

size_t é o tipo inteiro não assinado do resultado do operador sizeof (ISO C99, seção 7.17.)

O sizeofoperador gera o tamanho (em bytes) de seu operando, que pode ser uma expressão ou o nome entre parênteses de um tipo. O tamanho é determinado a partir do tipo do operando. O resultado é um número inteiro. O valor do resultado é definido pela implementação e seu tipo (um tipo inteiro não assinado) é size_t(ISO C99, Seção 6.5.3.4).

fpmurphy
fonte
A melhor resposta, como cita o padrão.
Martin Iorque
1
@ Martin - é verdade, mas acho que a parte da pergunta 'por que não é assinado?' É tão interessante (ou mais) quanto a parte 'o que é tamanho_t', e você não encontrará isso no padrão .
22909 Michael Burr
Sim, exceto que não há 'Seção 17.17 ': p. É raro, ninguém disse uma palavra sobre Void_t
Eliseo Ocampos
Aceito esta resposta, pois responde diretamente à pergunta, mas seria ótimo se fosse complementada com a resposta de Michael.
Eliseo Ocampos
58
Pena que sua resposta não me diga qual arquivo de cabeçalho incluir.
Matt
6

Na prática, size_trepresenta o número de bytes que você pode endereçar. Nas arquiteturas mais modernas dos últimos 10 a 15 anos, foram 32 bits, o que também tem o tamanho de um int não assinado. No entanto, estamos migrando para o endereçamento de 64 bits, enquanto o uintmais provável é permanecer em 32 bits (seu tamanho não é garantido no padrão c ++). Para tornar seu código que depende do tamanho da memória portátil entre arquiteturas, você deve usar a size_t. Por exemplo, coisas como tamanhos de matriz sempre devem usar size_t's. Se você observar os contêineres padrão, ::size()sempre retornará a size_t.

Observe também que o visual studio possui uma opção de compilação que pode verificar esses tipos de erros chamados "Detectar problemas de portabilidade de 64 bits".

Matt Price
fonte
2

Dessa forma, você sempre sabe qual é o tamanho, porque um tipo específico é dedicado aos tamanhos. A própria pergunta mostra que pode ser um problema: é um intou um unsigned int? Além disso, qual é a magnitude ( short, int, long, etc.)?

Como existe um tipo específico atribuído, você não precisa se preocupar com o comprimento ou a assinatura.

A definição real pode ser encontrada na Biblioteca de Referência C ++ , que diz:

Tipo: size_t(tipo integral não assinado)

Cabeçalho: <cstring>

size_tcorresponde ao tipo de dados integral retornado pelo operador de idioma sizeofe é definido no<cstring> arquivo de cabeçalho (entre outros) como um tipo integral não assinado.

Em <cstring>, é usado como o tipo do parâmetro numnas funções memchr,memcmp , memcpy, memmove, memset, strncat, strncmp, strncpye strxfrm, que, em todos os casos, é usado para especificar o número máximo de bytes ou caracteres a função tem que afectar.

Ele também é usado como o tipo de retorno para strcspn, strlen,strspn e strxfrmpara tamanhos de retorno e comprimentos.

lavinio
fonte
2

size_t deve ser definido nos cabeçalhos da sua biblioteca padrão. Na minha experiência, geralmente é simplesmente um typedef para unsigned int. O ponto, porém, é que não precisa ser. Tipos como size_t permitem ao fornecedor da biblioteca padrão a liberdade de alterar seus tipos de dados subjacentes, se apropriado para a plataforma. Se você assumir que size_t é sempre sem assinatura int (por meio de vazamento, etc), poderá ter problemas no futuro se o seu fornecedor alterar size_t para, por exemplo, um tipo de 64 bits. É perigoso assumir algo sobre esse ou qualquer outro tipo de biblioteca por esse motivo.

Ryan
fonte
1

Não estou familiarizado, void_texceto como resultado de uma pesquisa no Google (é usada em uma vmallocbiblioteca por Kiem-Phong Vo na AT&T Research - tenho certeza de que também é usada em outras bibliotecas).

Os vários xxx_t typedefs são usados ​​para abstrair um tipo de uma implementação definida específica, pois os tipos concretos usados ​​para certas coisas podem diferir de uma plataforma para outra. Por exemplo:

  • size_t abstrai o tipo usado para armazenar o tamanho dos objetos, porque em alguns sistemas esse será um valor de 32 bits; em outros, pode ser de 16 ou 64 bits.
  • Void_tabstrai o tipo de ponteiro retornado pelas vmallocrotinas da biblioteca porque foi gravado para funcionar em sistemas anteriores à ANSI / ISO C, em que ovoid palavra chave pode não existir. Pelo menos é o que eu acho.
  • wchar_t abstrai o tipo usado para caracteres largos, já que em alguns sistemas será do tipo 16 bits, em outros será de 32 bits.

Portanto, se você escrever seu código de manipulação de caracteres amplo para usar o wchar_ttipo em vez de, digamos unsigned short, esse código provavelmente será mais portátil para várias plataformas.

Michael Burr
fonte
Isto é o que eu estava procurando, em parte. Como eu disse em um comentário em resposta de fpmurphy, seria ótimo que ele pode ser complementado com esta resposta (Se você não se importa talvez você possa editá-lo) :)
Eliseo Ocampos
1

Em programas minimalistas em que uma size_tdefinição não foi carregada "por acaso" em algumas inclusões, mas eu ainda a necessito em algum contexto (por exemplo, para acessar std::vector<double>), então uso esse contexto para extrair o tipo correto. Por exemplotypedef std::vector<double>::size_type size_t .

(Coloque, namespace {...}se necessário, para tornar o escopo limitado.)

alfC
fonte
1

Quanto a "Por que não usar int ou unsigned int?", Simplesmente porque é semanticamente mais significativo não usar. Existe a razão prática de que ele pode ser, digamos, typedefd como inte depois atualizado para um longposterior, sem que ninguém precise alterar seu código, é claro, mas mais fundamentalmente do que um tipo deve ser significativo. Para simplificar bastante, uma variável do tipo size_té adequada e usada para conter os tamanhos das coisas, assim como time_té adequada para conter valores temporais. Como elas são realmente implementadas deve ser o trabalho da implementação. Comparado a apenas chamar tudo int, o uso de nomes de tipos significativos como esse ajuda a esclarecer o significado e a intenção do seu programa, assim como qualquer tipo rico de tipos.

Crowman
fonte