ssize_t - C: ¿Por qué no es size_t una palabra clave en C?
size_t c (10)
¿No significa esto algún tipo de problema en la especificación estándar de C?
Busque la diferencia entre una implementación de C alojada y una implementación de C independiente. La implementación independiente (C99) es necesaria para proporcionar encabezados:
-
<float.h>
-
<iso646.h>
-
<limits.h>
-
<stdarg.h>
-
<stdbool.h>
-
<stddef.h>
-
<stdint.h>
Estos encabezados no definen ninguna función en absoluto. Definen partes del lenguaje que son algo específicas del compilador (por ejemplo, la macro offsetof
de <stddef.h>
, y la lista de argumentos variables macros y tipos en <stdarg.h>
), pero se pueden manejar sin que realmente se construyan en el lenguaje como palabras clave completas.
Esto significa que incluso en su hipotético kernel, debe esperar que el compilador de C proporcione estos encabezados y cualquier función de soporte subyacente, aunque usted proporcione todo lo demás.
sizeof
es una palabra clave C Devuelve el tamaño en un tipo llamado size_t
. Sin embargo, size_t
no es una palabra clave, pero se define principalmente en stddef.h
y probablemente también en otros archivos de encabezado estándar de C.
Considere un escenario en el que desee crear un programa en C que no incluya ningún encabezado o biblioteca estándar en C. (Como por ejemplo, si está creando un kernel de SO). Ahora, en dicho código, se puede usar sizeof
(es una palabra clave C, por lo que es parte del idioma ), pero el tipo que devuelve ( size_t
) ¡no está disponible!
¿No significa esto algún tipo de problema en la especificación estándar de C? ¿Puedes aclarar esto?
Algunas cabeceras del estándar C están definidas para un entorno independiente , es decir, aptas para su uso, por ejemplo, en un kernel de sistema operativo. No definen ninguna función, simplemente define y typedefs.
Son float.h, iso646.h, limits.h, stdarg.h, stdbool.h, stddef.h y stdint.h.
Cuando se trabaja en un sistema operativo, no es una mala idea comenzar con estos encabezados. Tenerlos disponibles hace muchas cosas más fáciles en tu núcleo. Especialmente stdint.h será útil (uint32_t et al.).
Creo que las razones principales por las que size_t
no es una palabra clave son:
- No hay una razón convincente para que sea. Los diseñadores de los lenguajes C y C ++ siempre han preferido que las características del lenguaje se implementen en la biblioteca si es posible y razonable.
- agregar palabras clave a un idioma puede crear problemas para un cuerpo existente de código heredado. Esta es otra razón por la que generalmente se resisten a agregar nuevas palabras clave.
Por ejemplo, al analizar la próxima revisión importante del estándar C ++, Stroustrup dijo lo siguiente :
Las mejoras de C ++ 0x deben realizarse de tal manera que el lenguaje resultante sea más fácil de aprender y usar. Entre las reglas de oro para el comité están:
...
- Prefiere las instalaciones de la biblioteca estándar a las extensiones de idioma
...
Desde MSDN :
Cuando el operador sizeof se aplica a un objeto de tipo char, se obtiene 1
Incluso si no tiene stddef.h disponible / incluido y no sabe acerca de size_t, utilizando sizeof puede obtener el tamaño de los objetos en relación con char.
La razón simple es porque no es un tipo fundamental. Si busca el estándar C, encontrará que los tipos fundamentales incluyen int
, char
, etc. pero no size_t
. ¿Porque? Como otros ya han señalado, size_t
es un tipo específico de implementación (es decir, un tipo capaz de mantener el tamaño en número de "C bytes" de cualquier objeto).
Por otro lado, sizeof
es un operador (unario). Todos los operadores son palabras clave.
Literalmente no devuelve un valor de tipo size_t ya que size_t no es un tipo concreto en sí mismo, sino un typedef a un tipo incorporado no especificado. Los identificadores typedef (como size_t) son completamente equivalentes a sus respectivos tipos subyacentes (y se convierten a ellos en tiempo de compilación). Si size_t se define como un int sin signo en su plataforma, entonces sizeof devuelve un int sin signo cuando se compila en su sistema. size_t es solo una forma práctica de mantener la portabilidad y solo debe incluirse en stddef.h si lo está utilizando explícitamente por nombre.
No hay ninguna razón para no incluir stddef.h, incluso si está trabajando en un núcleo: define los tamaños de tipo para su compilador específico que necesitará cualquier código.
Tenga en cuenta también que casi todos los compiladores de C son autocompilados. Por lo tanto, el código del compilador real para el operador sizeof utilizará size_t y hará referencia al mismo archivo stddef.h que el código de usuario.
size_t es en realidad un tipo, a menudo un int sin signo. Sizeof es un operador que da el tamaño de un tipo. El tipo devuelto por sizeof es en realidad específico de la implementación, no es un estándar de C. Es sólo un número entero.
Edición: Para ser muy claro, no necesita el tamaño size_t para poder utilizar sizeof. Creo que la respuesta que estás buscando es - Sí, es inconsistente. Sin embargo, no importa. Aún puede usar prácticamente sizeof correctamente sin tener una definición size_t de un archivo de encabezado.
sizeof
es una palabra clave porque, a pesar de su nombre y uso, es un operador como +
o =
o <
lugar de una función como printf()
o atoi()
o fgets()
. Mucha gente olvida (o simplemente no sabe) que sizeof
es en realidad un operador, y siempre se resuelve en tiempo de compilación en lugar de en tiempo de ejecución.
El lenguaje C no necesita que size_t
sea un lenguaje utilizable y consistente. Eso es sólo una parte de la biblioteca estándar. El lenguaje C necesita todos los operadores. Si, en lugar de +
, C usara la palabra clave plus
para agregar números, lo convertiría en un operador.
Además, hago una refundición semi-implícita de size_t
s a unsigned int
s (y int
s, pero Kernighan y Ritchie algún día me castigarán por esto) todo el tiempo. Si lo desea, puede asignar el tipo de retorno de una sizeof
a un int, pero en mi trabajo por lo general solo lo paso directamente a un malloc()
o algo así.
size_t no es una palabra clave por necesidad. Las diferentes arquitecturas a menudo tienen diferentes tamaños para los tipos integrales. Por ejemplo, es probable que una máquina de 64 bits tenga una firma sin firmar durante tanto tiempo como tamaño_t si no decidieron hacer int un tipo de datos de 64 bits.
Si creas el tamaño de un tipo integrado en el compilador, entonces le quitará el poder a la compilación cruzada.
Además, sizeof es más como una macro de tiempo de compilación mágica (piense en la plantilla c ++) que explica por qué es una palabra clave en lugar de un tipo definido.