<cstdint> vs <stdint.h>

95

Qual é a diferença entre stdint.he cstdint?

Ambos estão disponíveis em MSVC (Visual Studio 2010) e gcc-4.5.1. Além disso, ambos definem os tipos intX_t/ uintX_t(onde Xé o tamanho em bytes do tipo).

  • Se a lógica em ambos os cabeçalhos for a mesma (tipos portáteis), que decisões devo tomar para decidir sobre um ou outro?

O stdint.hdefine cada tipo sem nenhum namespace, os cstdinttipos estão no stdnamespace.

  • Há algum motivo para incluir ou não os tipos definidos no stdnamespace? O que é diferente entre os dois cabeçalhos?

cstdintnão tem extensão de arquivo e usa o cprefixo, stdint.husa a .hextensão.

  • Quais são as convenções de nomenclatura para esses cabeçalhos? o cprefixo indica que esta é uma biblioteca C? há uma razão para a falta de extensão de arquivo em cstdint?
PaperBirdMaster
fonte
OS X 10.8 carece <cstdint>. Aqui está o erro que eu recebo: ./misc.h:7:10: fatal error: 'cstdint' file not found.
jww

Respostas:

122

A intenção original em C ++ 98 era que você deveria usar <cstdint>em C ++, para evitar poluir o namespace global (bem, não <cstdint>em particular, isso só é adicionado em C ++ 11, mas os <c*>cabeçalhos em geral).

No entanto, as implementações persistiram em colocar os símbolos no namespace global de qualquer maneira, e o C ++ 11 ratificou essa prática [*]. Então, você tem basicamente três opções:

  • Use <cstdint>e qualifique totalmente cada tipo de número inteiro que você usa ou traga-o para o escopo com using std::int32_t;etc (irritante porque prolixo, mas é a maneira certa de fazer isso como para qualquer outro símbolo na biblioteca padrão C ++)
  • Use <stdint.h>(um pouco ruim porque obsoleto)
  • Use <cstdint>e presuma que sua implementação colocará os símbolos no namespace global (muito ruim porque não é garantido).

Na prática, suspeito que uma grande quantidade de código irritante usa a última opção, simplesmente porque é fácil de fazer por acidente em uma implementação onde <cstdint>coloca os símbolos no namespace global. Você deve tentar usar o primeiro. O segundo tem uma virtude, que é garantido colocar coisas no namespace global em vez de apenas fazer isso. Não acho isso particularmente útil, mas pode economizar um pouco de digitação se essa for sua prioridade.

Há uma quarta opção, #include <cstdint>seguida da using namespace std;que às vezes é útil, mas há lugares que você não deve colocar using namespace std;. Pessoas diferentes terão idéias diferentes sobre onde esses lugares estão, mas "no nível superior em um arquivo de cabeçalho" é pior do que "no nível superior em um arquivo cpp", que é pior do que "em um escopo limitado". Algumas pessoas nunca escrevem using namespace std;.

[*] Isso significa que os cabeçalhos padrão C ++ têm permissão para colocar coisas no namespace global, mas não é obrigatório. Portanto, você deve evitar a colisão com esses símbolos, mas não pode realmente usá-los porque eles podem não estar lá. Basicamente, o namespace global em C ++ é um campo minado, tente evitá-lo. Pode-se argumentar que o comitê ratificou uma prática por implementações que é quase tão prejudicial quanto furar using namespace std;no nível superior em um arquivo de cabeçalho - a diferença é que as implementações só fazem isso para símbolos na biblioteca padrão C, enquanto o using namespace std;faz para C ++ - apenas símbolos também. Há uma seção no padrão C que lista nomes reservados para adições futuras ao padrão. Não é uma ideia completamente estúpida tratar esses nomes como reservados no namespace global C ++ também, mas não é essencial.

Steve Jessop
fonte
A única pergunta sem resposta que permanece é sobre as convenções de nomenclatura dos arquivos de cabeçalho. Você conhece este tópico?
PaperBirdMaster
24
@PaperBirdMaster: C ++ cabeçalhos da biblioteca padrão não têm extensões de arquivo: <iostream>, <vector>, <cstdlib>, para além de os incluídos para compatibilidade C: <stdint.h>, <stdlib.h>. E sim, a inicial cindica que <cstdlib>é o equivalente em C ++ do cabeçalho padrão C <stdlib.h>, em vez de ser totalmente novo em C ++ como <vector>é. Há um cabeçalho C ++ <complex>, então, teremos que torcer para que nenhuma versão futura do C introduza um cabeçalho padrão <omplex.h>.
Steve Jessop
@SteveJessop Erm, C99?
SS Anne de
1
@ JL2210 aviso que ele disse <omplex.h>, não <complex.h>. Se C adicionado <omplex.h>, o equivalente em C ++ seria <complex>.
John Leuenhagen
16

Incluir cstdintimporta os nomes dos símbolos no namespace std e possivelmente no namespace Global.
Incluir stdint.himporta os nomes dos símbolos no namespace global e possivelmente no namespace std.

Os recursos da biblioteca padrão C também são fornecidos na biblioteca padrão C ++ e, como uma convenção geral de nomenclatura, eles são precedidos por um c aos nomes correspondentes na biblioteca padrão C.

Em C ++, você deve usar:

#include <cstdint>

e qualificar totalmente os nomes de símbolo que você usa std::
enquanto em C, você deve usar:

#include <stdint.h>

Anexo D (normativo) Características de compatibilidade [depr] estados:

Cabeçalhos de biblioteca padrão D.6 C

1 Para compatibilidade com a biblioteca padrão C e C Unicode TR, a biblioteca padrão C ++ fornece os 25 cabeçalhos C, conforme mostrado na Tabela 151.

Que incluem:

<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>

E além disso,

2 Cada cabeçalho C, cada um com um nome do formulário name.h, se comporta como se cada nome colocado no namespace da biblioteca padrão pelo correspondente cname headerfosse colocado no escopo do namespace global. Não é especificado se esses nomes são primeiro declarados ou definidos no escopo do namespace (3.3.6) do namespace std e, em seguida, são injetados no escopo do namespace global por declarações de uso explícitas (7.3.3).

3 [Exemplo: O cabeçalho <cstdlib>fornece com certeza suas declarações e definições dentro do namespace std. Ele também pode fornecer esses nomes no namespace global. O cabeçalho <stdlib.h>certamente fornece as mesmas declarações e definições dentro do namespace global, assim como no C Standard. Ele também pode fornecer esses nomes no espaço de nomes std. —End exemplo]

Alok Save
fonte
-1
  1. cstdinté o cabeçalho C ++ 11, stdint.hé o cabeçalho C99 (C e C ++ são linguagens diferentes!)

  2. MSVC 2008 não contém stdint.hnem cstdint.

  3. A cstdintmaioria das implementações de são simplesmente #include <stdint.h>com algumas correções de namespace / linguagem.

motor do ódio
fonte
2
3. está errado. cstdintprecisa içar as implementações para o namespace std.
Konrad Rudolph
1
1. também está errado, stdint.h é definido como uma parte da biblioteca C ++ no anexo D normativo do padrão C ++.
chill
@chill, você poderia fornecer um link para o Anexo D? Aqui en.cppreference.com/w/cpp/types/integer declarou que é o cabeçalho C ++ 11.
motor do ódio
1
@odeio-engine, sugiro que você procure em sua cópia do padrão C ++. Essa página de preferência não menciona stdint.h. Não há nenhum argumento que cstdintseja um cabeçalho C ++.
chill
2
Nenhuma parte de 1. é falsa, apenas que, em conjunto, parece que você está dizendo que stdint.hnão faz parte do C ++ 11. Na verdade, é exigido pelo C ++ 11. Você poderia dizer, " intestá em C ++ 11; longestá em C99; C e C ++ são linguagens diferentes!", E nenhuma parte disso também seria falsa. Meu exemplo é ainda mais enganoso, pois C ++ 11 se refere em parte a C99 para definir o conteúdo de ambos stdint.he cstdint, mas não se refere a C para definir int.
Steve Jessop