<cstdint> frente a <stdint.h>

95

¿Cuál es la diferencia entre stdint.hy cstdint?

Ambos están disponibles en MSVC (Visual Studio 2010) y gcc-4.5.1. También ambos definen los tipos intX_t/ uintX_t(donde Xes el tamaño en bytes del tipo).

  • Si el fundamento en ambos encabezados es el mismo (tipos portátiles), ¿qué decisiones debo tomar para decidir sobre uno u otro?

El stdint.hdefine cada tipo sin ningún espacio de nombres, los cstdinttipos se encuentra en el stdespacio de nombres.

  • ¿Hay alguna razón para incluir o no incluir los tipos definidos en el stdespacio de nombres? ¿Qué es diferente entre los dos encabezados?

cstdintno tiene extensión de archivo y usa el cprefijo, stdint.husa la .hextensión.

  • ¿Cuáles son las convenciones de nomenclatura para estos encabezados? el cprefijo indica que se trata de una biblioteca C? hay una razón para la falta de extensión de archivo en cstdint?
PaperBirdMaster
fuente
OS X 10.8 carece <cstdint>. Aquí está el error que recibo: ./misc.h:7:10: fatal error: 'cstdint' file not found.
jww

Respuestas:

123

La intención original en C ++ 98 era que se usara <cstdint>en C ++, para evitar contaminar el espacio de nombres global (bueno, no <cstdint>en particular, eso solo se agrega en C ++ 11, pero los <c*>encabezados en general).

Sin embargo, las implementaciones persistieron en poner los símbolos en el espacio de nombres global de todos modos, y C ++ 11 ratificó esta práctica [*]. Entonces, básicamente tienes tres opciones:

  • Use <cstdint>y califique completamente cada tipo de entero que use o bien, llévelo al alcance con using std::int32_t;etc. (molesto porque es detallado, pero es la forma correcta de hacerlo como para cualquier otro símbolo en la biblioteca estándar de C ++)
  • Uso <stdint.h>(levemente malo porque obsoleto)
  • Use <cstdint>y asuma que su implementación colocará los símbolos en el espacio de nombres global (muy mal porque no está garantizado).

En la práctica, sospecho que una gran cantidad de código molesta usa la última opción, simplemente porque es fácil de hacer por accidente en una implementación donde se <cstdint>colocan los símbolos en el espacio de nombres global. Deberías intentar usar el primero. La segunda tiene una virtud, que está garantizado poner cosas en el espacio de nombres global en lugar de solo hacerlo tal vez. No creo que eso sea particularmente útil, pero podría ahorrar algo de escritura si esa es su prioridad.

Hay una cuarta opción, #include <cstdint>seguida de la using namespace std;que a veces es útil, pero hay lugares en los que no debes poner el using namespace std;. Diferentes personas tendrán diferentes ideas sobre dónde están esos lugares, pero "en el nivel superior en un archivo de encabezado" es peor que "en el nivel superior en un archivo cpp", que es peor que "en un alcance limitado". Algunas personas nunca escriben using namespace std;en absoluto.

[*] Eso significa que los encabezados estándar de C ++ pueden poner cosas en el espacio de nombres global, pero no es obligatorio. Por lo tanto, debe evitar chocar con esos símbolos, pero en realidad no puede usarlos porque es posible que no estén allí. Básicamente, el espacio de nombres global en C ++ es un campo minado, trate de evitarlo. Se podría argumentar que el comité ha ratificado una práctica mediante implementaciones que es casi tan dañina como quedarse using namespace std;en el nivel superior en un archivo de encabezado; la diferencia es que las implementaciones solo lo hacen para símbolos en la biblioteca estándar de C, mientras using namespace std;que lo hace para C ++ -sólo símbolos también. Hay una sección en el estándar C que enumera los nombres reservados para futuras adiciones al estándar. No es una idea completamente estúpida tratar esos nombres como reservados en el espacio de nombres global de C ++ también, pero no es esencial.

Steve Jessop
fuente
La única pregunta sin respuesta que queda es sobre las convenciones de nomenclatura de los archivos de encabezado, ¿conoce este tema?
PaperBirdMaster
24
@PaperBirdMaster: cabeceras de la biblioteca estándar de C ++ no tienen extensiones de archivo: <iostream>, <vector>, <cstdlib>, aparte de las que se incluyen la compatibilidad C: <stdint.h>, <stdlib.h>. Y sí, la inicial cindica que <cstdlib>es el equivalente de C ++ del encabezado estándar de C <stdlib.h>, en lugar de ser completamente nuevo en C ++ como <vector>es. Hay un encabezado C ++ <complex>, por lo que tendremos que esperar que ninguna versión futura de C introduzca un encabezado estándar <omplex.h>.
Steve Jessop
@SteveJessop Erm, C99?
SS Anne
1
@ JL2210 note que dijo <omplex.h>, no <complex.h>. Si se agrega C <omplex.h>, el equivalente de C ++ sería <complex>.
John Leuenhagen
16

Incluir las cstdintimportaciones de los nombres de los símbolos en el espacio de nombres estándar y posiblemente en el espacio de nombres global.
Incluir las stdint.himportaciones de los nombres de los símbolos en el espacio de nombres global y posiblemente en el espacio de nombres estándar.

Las características de la biblioteca estándar de C también se proporcionan en la biblioteca estándar de C ++ y, como convención general de nomenclatura, están precedidas por una c a los nombres correspondientes en la biblioteca estándar de C.

En C ++, deberías usar:

#include <cstdint>

y calificar completamente los nombres de símbolo que usa std::
mientras está en C, debe usar:

#include <stdint.h>

El anexo D (normativo) Características de compatibilidad [depr] establece:

D.6 encabezados de biblioteca estándar de C

1 Para compatibilidad con la biblioteca estándar C y C Unicode TR, la biblioteca estándar C ++ proporciona los 25 encabezados C, como se muestra en la Tabla 151.

Que incluye:

<assert.h> <float.h> <math.h> <stddef.h> <tgmath.h> <complex.h> <inttypes.h> <setjmp.h> <stdio.h> <time.h> <ctype.h> <iso646.h> <signal.h> <stdint.h> <uchar.h> <errno.h> <limits.h> <stdarg.h> <stdlib.h> <wchar.h> <fenv.h> <locale.h> <stdbool.h> <string.h> <wctype.h>

Y además,

2 Cada encabezado C, cada uno de los cuales tiene un nombre del formulario name.h, se comporta como si cada nombre colocado en el espacio de nombres de biblioteca estándar por el correspondiente cname headerse ubicara dentro del ámbito del espacio de nombres global. No se especifica si estos nombres se declaran o definen primero dentro del ámbito del espacio de nombres (3.3.6) del espacio de nombres std y luego se inyectan en el ámbito del espacio de nombres global mediante declaraciones de uso explícitas (7.3.3).

3 [Ejemplo: el encabezado <cstdlib>seguramente proporciona sus declaraciones y definiciones dentro del espacio de nombres std. También puede proporcionar estos nombres dentro del espacio de nombres global. El encabezado <stdlib.h>seguramente proporciona las mismas declaraciones y definiciones dentro del espacio de nombres global, como en el estándar C. También puede proporcionar estos nombres dentro del espacio de nombres std. —Ejemplo final]

Alok Save
fuente
-1
  1. cstdintes el encabezado C ++ 11, stdint.hes el encabezado C99 (¡C y C ++ son lenguajes diferentes!)

  2. MSVC 2008 no contiene stdint.hni cstdint.

  3. Las implementaciones de cstdintson en su mayoría simplemente #include <stdint.h>con algunas correcciones de espacio de nombres / lenguaje.

motor de odio
fuente
2
3. está mal. cstdintnecesita subir las implementaciones al espacio de nombres std.
Konrad Rudolph
1
1. también es incorrecto, stdint.h se define como parte de la biblioteca C ++ en el Anexo D normativo del estándar C ++.
relajarse
@chill, ¿podría proporcionar un enlace al anexo D? Aquí en.cppreference.com/w/cpp/types/integer declaró que es el encabezado de C ++ 11.
motor de odio
1
@ hate-engine, te sugiero que lo busques en tu copia del estándar C ++. Esa página de referencia de cpp no ​​menciona stdint.h. No hay ningún argumento que cstdintsea ​​un encabezado C ++.
relajarse
2
Ninguna parte de 1. es falsa, es solo que, en conjunto, parece que estás diciendo stdint.hque no es parte de C ++ 11. De hecho, es requerido por C ++ 11. Se podría decir " intestá en C ++ 11; longestá en C99; ¡C y C ++ son lenguajes diferentes!", Y ninguna parte de eso tampoco sería falsa. Sin embargo, mi ejemplo es aún más engañoso, ya que C ++ 11 se refiere en parte a C99 para definir el contenido de ambos stdint.hy cstdint, pero no se refiere a C para definirlo int.
Steve Jessop