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?
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.
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.
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.
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.
Respostas:
C
size_t
e C ++std::size_t
sã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,
E o C ++ Standard diz (sobre o
cstddef
cabeçalho) no §18.1 / 3,Então sim, ambos são iguais; a única diferença é que o C ++ define
size_t
nostd
espaç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:
E o resto você pode ler nesta página na wikipedia.
fonte
size_t
semusing namespace std;
ouusing std::size_t;
. No entanto, a maioria dos compiladores permite, e o Padrão especificamente permite que eles o permitam (§D.5 / 3).<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.::size_t
está presente, por exemplo<stddef.h>
, no , portanto nem sempre é necessário qualificá-lostd::
.No C ++ 03 "Tipos 17.4.3.1.4":
E nota de rodapé 169:
fonte
std::T
variantes definidas?#include <stddef.h>
, em seguida,std::size_t
pode ou não estar disponível. Se você#include <cstddef>
, em seguida,std::size_t
está disponível, massize_t
pode não ser.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 nostd::
nível superior. A maioria dos compiladores inclui apenas o cabeçalho C e importa os nomes parastd::
, então os símbolos acabam definidos em ambos.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>
esize_t
e nunca dar um segundo pensamento parastd::size_t
; de fato, nunca me ocorre que exista (ou possa haver) astd::size_t
.std :: size_t é de fato stddef.h 's size_t .
cstddef fornece o seguinte:
... efetivamente trazendo a definição anterior para o espaço de nome std.
fonte
<cstddef>
e espera receber::size_t
, mas se incluir<stddef.h>
, receberástd::size_t
.<stddef.h>
apenas o levará::size_t
.<cstddef>
é garantido o recebimentostd::size_t
e também poderá obter::size_t
(mas não é garantido). Se você incluir,<stddef.h>
é garantido o recebimento::size_t
e também poderá receberstd::size_t
(mas não é garantido). Era diferente no C ++ 03, mas era efetivamente não implementável e corrigido como um defeito.