Diferencia entre size_t y std :: size_t

139

¿Cuáles son las diferencias entre size_ty std::size_ten términos de dónde se declaran, cuándo deben usarse y otras características diferenciadoras?

Mankarse
fuente
Me interesaría saber si la especificación de C ++ vincula std :: size_t al tipo C size_t.
Doug T.
Ver pregunta similar: enlace
Mankarse

Respuestas:

88

C size_ty C ++ std::size_tson los mismos.

En C, se define en <stddef.h>y en C ++, se define en <cstddef>cuyo contenido es el mismo que el encabezado C (consulte la cita a continuación). Se define como un tipo entero sin signo del resultado del operador sizeof .

C Standard dice en §17.7 / 2,

size_t, que es el tipo entero sin signo del resultado del operador sizeof

Y el estándar C ++ dice (sobre el cstddefencabezado) en §18.1 / 3,

El contenido es el mismo que el encabezado de la biblioteca estándar C, con los siguientes cambios .

Entonces sí, ambos son iguales; La única diferencia es que C ++ define size_ten el stdespacio de nombres.

Tenga en cuenta también que la línea anterior también dice "con los siguientes cambios" a los que no se refiere size_t. Se refiere más bien a las nuevas adiciones (en su mayoría) realizadas por C ++ en el lenguaje (no presente en C) que también se definen en el mismo encabezado.


Wikipedia tiene muy buena información sobre el rango y el tamaño de almacenamiento de size_t:

Rango y tamaño de almacenamiento de size_t

El tipo real de size_t depende de la plataforma ; un error común es asumir que size_t es lo mismo que unsigned int, lo que puede conducir a errores de programación, [3] [4] al pasar de una arquitectura de 32 a 64 bits, por ejemplo.

Según el estándar ISO C 1999 (C99), size_t es un tipo entero sin signo de al menos 16 bits.

Y el resto lo puedes leer desde esta página en wikipedia.

Nawaz
fuente
Eso lleva a otra Q, si STL ya importa size_t a través de C (cstddef), ¿por qué tiene su propia otra versión nuevamente?
Alok Save
43
@Als: Estrictamente hablando, es un error decir size_tsin using namespace std;o using std::size_t;. Sin embargo, la mayoría de los compiladores lo permiten, y el Estándar específicamente les permite permitirlo (§D.5 / 3).
Potatoswatter
9
@Potatoswatter: ¿Seguramente no puede ser tanto un error como específicamente permitido en el estándar? Si está en el estándar, ¡no es un error!
Ben Hymers
8
@BenHymers El estándar especifica lo que declaran los encabezados estándar, y no se les permite declarar ningún otro nombre no reservado. El encabezado <cstddef>puede o no declararse ::size_t, por lo que no puede confiar en que esté allí o esté ausente, a menos que incluya específicamente <stddef.h>u otro encabezado de la biblioteca C que garantice su declaración.
Potatoswatter
44
@Potatoswatter: ¡Ah, ahora entiendo lo que quieres decir! Debo haberme confundido con demasiados "permisos" en una oración. Sin embargo, sigo pensando que tu primer comentario es demasiado fuerte; como acabas de decir, ::size_testá presente <stddef.h>, por ejemplo , en , por lo que no siempre necesitas calificarlo std::.
Ben Hymers
16

Desde C ++ 03 "17.4.3.1.4 Tipos":

Para cada tipo T de la biblioteca C estándar (nota 169), los tipos :: T y std :: T están reservados para la implementación y, cuando se define, :: T será idéntico a std :: T.

Y nota 169:

Estos tipos son 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 y wint_t.

Michael Burr
fuente
¿Entonces el código portátil no debería depender de las std::Tvariantes que se definen?
Mankarse
55
@Mankarse: No debe confiar en que se definan si solo incluye la versión C del encabezado correspondiente. Si #include <stddef.h>luego std::size_tpuede o no estar disponible. Si #include <cstddef>entonces std::size_testá disponible, pero size_tpodría no estarlo.
Dennis Zickefoose
44
@Mankarse: El opuesto. Las versiones C ++ de los encabezados deben definirlos std::y el párrafo dice que también puede definirlos en el espacio de nombres de nivel superior y, si lo hace, debe definirlos de manera idéntica std::y en el nivel superior. La mayoría de los compiladores solo incluyen el encabezado C e importan los nombres std::, por lo que los símbolos terminan definidos en ambos.
Jan Hudec
44
Personalmente, nunca me molesto con los encabezados <cxxxxx> o las std::variantes de identificadores que provienen de la orilla C. Me quedo con <xxxxx.h>los encabezados C estándar: nunca ha sido un problema. Por lo tanto, me gustaría usar <stddef.h>y size_tnunca dar un segundo pensamiento a std::size_t; de hecho, nunca se me ocurre que hay (o podría haber) a std::size_t.
Michael Burr
12

std :: size_t es de hecho stddef.h 's size_t .

cstddef da lo siguiente:

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

... trayendo efectivamente la definición anterior al espacio de nombres estándar.

hifier
fuente
Como señala Nawaz, en realidad es al revés. No puede incluir <cstddef>y esperar obtener ::size_t, pero si lo incluye <stddef.h>, obtendrá std::size_t.
MSalters
44
@MSalters, no te sigo. La inclusión <stddef.h>solo te atrapará ::size_t.
hifier
2
Eso es un error en su implementación, entonces.
MSalters
44
@MSalters, no entiendo del todo. ¿No debería ser al revés? <cstddef> proviene de C ++, por lo tanto, ¿debería definir las cosas en std :: *? Por otro lado, en un encabezado C, como stddef.h, solo esperaría el tipo C, es decir :: size_t.
Ela782
11
@MSalters, ya que C ++ 11 no es exacto. Si incluye <cstddef>, tiene garantizado obtener std::size_ty también puede obtener ::size_t(pero no está garantizado). Si incluye <stddef.h>está garantizado obtener ::size_ty también puede obtener std::size_t(pero no está garantizado). Era diferente en C ++ 03, pero eso no fue implementable y se solucionó como un defecto.
Jonathan Wakely