Diferença entre size_t e std :: size_t

139

Quais são as diferenças entre size_te std::size_tem termos de onde são declaradas, quando devem ser usadas e quaisquer outras características diferenciadoras?

Mankarse
fonte
Eu estaria interessado em saber se a especificação C ++ vincula std :: size_t ao tipo C size_t.
Doug T.
Veja pergunta semelhante: link
Mankarse

Respostas:

88

C size_te C ++ std::size_tsão ambos iguais.

Em C, é definido em <stddef.h>e em C ++, sendo definido em <cstddef>cujo conteúdo é igual ao cabeçalho C (veja a citação abaixo). É definido como um tipo inteiro não assinado do resultado do operador sizeof .

O Padrão C diz em § 17.7 / 2,

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

E o C ++ Standard diz (sobre o cstddefcabeçalho) no §18.1 / 3,

O conteúdo é o mesmo que o cabeçalho da biblioteca Standard C, com as seguintes alterações .

Então sim, ambos são iguais; a única diferença é que o C ++ define size_tno stdespaço para nome.

Observe também que a linha acima também diz "com as seguintes alterações", à qual não se refere size_t. É mais uma referência às novas adições (principalmente) feitas por C ++ na linguagem (não presente em C), que também são definidas no mesmo cabeçalho.


A Wikipedia tem informações muito boas sobre o alcance e o tamanho de armazenamento de size_t:

Intervalo e tamanho de armazenamento de 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, [3] [4] ao passar da arquitetura de 32 para 64 bits, por exemplo.

De acordo com o padrão ISO C de 1999 (C99), size_t é um tipo inteiro não assinado de pelo menos 16 bits.

E o resto você pode ler nesta página na wikipedia.

Nawaz
fonte
Isso traz para outro Q, se o STL já importa size_t através de C (cstddef), por que ele tem sua própria outra versão novamente?
Alok Save
43
@ Als: Estritamente falando, é um erro dizer size_tsem using namespace std;ou using std::size_t;. No entanto, a maioria dos compiladores permite, e o Padrão especificamente permite que eles o permitam (§D.5 / 3).
Potatoswatter
9
@ Potatoswatter: Certamente não pode ser um erro e especificamente permitido no padrão? Se está no padrão, não é um erro!
Ben Hymers
8
@BenHymers O padrão especifica o que os cabeçalhos padrão declaram e não têm permissão para declarar outros nomes não reservados. O cabeçalho <cstddef>pode ou não declarar ::size_t, portanto, você não pode confiar nele ou ausente, a menos que inclua especificamente <stddef.h>ou outro cabeçalho da biblioteca C que seja garantido para declará-lo.
Potatoswatter
4
@ Potatoswatter: Ah, entendo o que você quer dizer agora! Devo ter ficado confuso com muitos "permissores" em uma frase. Ainda acho que seu primeiro comentário é muito forte; como você acabou de dizer, ::size_testá presente, por exemplo <stddef.h>, no , portanto nem sempre é necessário qualificá-lo std::.
Ben Hymers
16

No C ++ 03 "Tipos 17.4.3.1.4":

Para cada tipo T da biblioteca Standard C (nota de rodapé 169), os tipos :: T e std :: T são reservados para a implementação e, quando definidos, :: T devem ser idênticos a std :: T.

E nota de rodapé 169:

Esses tipos são clock_t, div_t, FILE, fpos_t, lconv, ldiv_t, mbstate_t, ptrdiff_t, sig_atomic_t, size_t, time_t, tm, va_list, wctrans_t, wctype_t e wint_t.

Michael Burr
fonte
Portanto, o código portátil não deve confiar nas std::Tvariantes definidas?
precisa saber é o seguinte
5
@Ankarse: você não deve confiar neles sendo definidos se você incluir apenas a versão C do cabeçalho correspondente. Se você #include <stddef.h>, em seguida, std::size_tpode ou não estar disponível. Se você #include <cstddef>, em seguida, std::size_testá disponível, mas size_tpode não ser.
Dennis Zickefoose
4
@Mankarse: O oposto. As versões C ++ dos cabeçalhos devem defini-los std::e o parágrafo diz que também pode defini-los no namespace de nível superior e, se o fizer, deve defini-los de forma idêntica no std::nível superior. A maioria dos compiladores inclui apenas o cabeçalho C e importa os nomes para std::, então os símbolos acabam definidos em ambos.
Jan Hudec
4
Pessoalmente, nunca me importo com os cabeçalhos <cxxxxx> ou com as std::variantes de identificadores que vêm da costa C. Eu fico com <xxxxx.h>os cabeçalhos C padrão - nunca foi um problema. Então, eu uso <stddef.h>e size_te nunca dar um segundo pensamento para std::size_t; de fato, nunca me ocorre que exista (ou possa haver) a std::size_t.
22711 Michael Burr
12

std :: size_t é de fato stddef.h 's size_t .

cstddef fornece o seguinte:

#include <stddef.h>
namespace std 
{
  using ::ptrdiff_t;
  using ::size_t;
}

... efetivamente trazendo a definição anterior para o espaço de nome std.

hifier
fonte
Como Nawaz aponta, na verdade é o contrário. Você não pode incluir <cstddef>e espera receber ::size_t, mas se incluir <stddef.h>, receberá std::size_t.
MSalters
4
@MSalters, eu não sigo. Incluir <stddef.h>apenas o levará ::size_t.
hifier
2
Isso é um bug na sua implementação, então.
MSalters
4
@MSalters, não entendo direito. Não deveria ser o contrário? <cstddef> vem do C ++, portanto, deve definir o material em std :: *? Por outro lado, em um cabeçalho C, como stddef.h, eu esperaria apenas o tipo C, ou seja, :: size_t.
Ela782
11
@MSalters, já que o C ++ 11 não é preciso. Se você incluir, <cstddef>é garantido o recebimento std::size_te também poderá obter ::size_t(mas não é garantido). Se você incluir, <stddef.h>é garantido o recebimento ::size_te também poderá receber std::size_t(mas não é garantido). Era diferente no C ++ 03, mas era efetivamente não implementável e corrigido como um defeito.
Jonathan Wakely