Como sizeof funciona para tipos int?
-
14-11-2019 - |
Pergunta
Eu tenho um pequeno programa que compara
(1) Sizeof, (2) numeric_limits :: dígitos, (3) e os resultados de um loop
em um esforço para garantir que todos relatem a mesma coisa em relação ao tamanho dos "tipos int" em qualquer implementação C++.No entanto, como não sei sobre os detalhes internos de sizeof, tenho que me perguntar se ele está apenas relatando numeric_limits::digits.Obrigado
Solução
Provavelmente sizeof()
na maioria dos compiladores faz com que o compilador pareça o tipo dado (ou o tipo de objeto) em sua tabela de tipo interno e insira um literal para o tamanho definido do tipo no código que gera. Isso aconteceria no tempo de compilação , não tempo de execução.
Para responder a pergunta nos comentários, não há acesso definido por idioma aos internos do compilador em C ++ (fora das coisas como a própria geragem, é claro).A única linguagem semelhante que eu conheço que permite que você faça coisas assim é Ada, que fornece asis Para escrever ferramentas de análise de código independente do compilador.
Outras dicas
O sizeof
operador é uma construção de tempo de compilação pela qual o compilador relata o tamanho, em bytes, que uma instância de um determinado tipo ocupará na memória.
É difícil dar uma resposta geral "é assim que sizeof funciona" porque é específica para cada implementação de compilador.Em em geral embora funcione calculando o tamanho de cada campo de um tipo e somando-os enquanto contabiliza o alinhamento.
Por exemplo, aqui está um conjunto razoável de resultados [1]
struct S1 {
int field1;
int field2;
};
struct S2 {
int field1;
bool field2;
int field3;
}
sizeof(S1) == 8
sizeof(S2) == 12;
A razão pela qual muitos compiladores relatarão o tamanho do S2
como 12 em oposição a 9 é que ele deve levar em conta problemas de alinhamento e, portanto, inserir 3 bytes para compensar a lacuna entre field2
e field3
[1] Nota:Eu disse razoável, não garantido :).As compilações C têm muita flexibilidade em tamanhos e é quase impossível especificar detalhes sobre tamanhos sem conhecer o compilador com o qual você está trabalhando
Não há muitos internos para sizeof
;é um operador integrado que informa o tamanho do seu operando (uma expressão ou um tipo) em bytes.
Seu código é bastante complexo - e usando typeid
me deixa pensando...
Tenho um programa bilíngue (escrito no subconjunto C de C++) que produz respostas como:
1 = sizeof(char)
1 = sizeof(unsigned char)
2 = sizeof(short)
2 = sizeof(unsigned short)
4 = sizeof(int)
4 = sizeof(unsigned int)
8 = sizeof(long)
8 = sizeof(unsigned long)
4 = sizeof(float)
8 = sizeof(double)
16 = sizeof(long double)
8 = sizeof(size_t)
8 = sizeof(ptrdiff_t)
8 = sizeof(time_t)
8 = sizeof(void *)
8 = sizeof(char *)
8 = sizeof(short *)
8 = sizeof(int *)
8 = sizeof(long *)
8 = sizeof(float *)
8 = sizeof(double *)
8 = sizeof(int (*)(void))
8 = sizeof(double (*)(void))
8 = sizeof(char *(*)(void))
1 = sizeof(struct { char a; })
2 = sizeof(struct { short a; })
4 = sizeof(struct { int a; })
8 = sizeof(struct { long a; })
4 = sizeof(struct { float a; })
8 = sizeof(struct { double a; })
16 = sizeof(struct { char a; double b; })
16 = sizeof(struct { short a; double b; })
16 = sizeof(struct { long a; double b; })
4 = sizeof(struct { char a; char b; short c; })
16 = sizeof(struct { char a; char b; long c; })
4 = sizeof(struct { short a; short b; })
6 = sizeof(struct { char a[3]; char b[3]; })
8 = sizeof(struct { char a[3]; char b[3]; short c; })
16 = sizeof(struct { long double a; })
32 = sizeof(struct { char a; long double b; })
(Isso foi produzido pelo G++ 4.6.0 no MacOS X 10.6.7 - uma compilação de 64 bits).O código que usei é:
#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#endif /* __cplusplus */
#include <stdio.h>
#include <time.h>
#include <stddef.h>
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
#include <inttypes.h>
#endif /* __STDC_VERSION__ */
/* Using the simple C code in SPRINT() for structures leads to complaints from G++ */
/* Using the code in TPRINT() for pointers to functions leads to other complaints */
#define TPRINT(x) do { typedef x y; printf("%2u = sizeof(" #x ")\n", (unsigned int)sizeof(y)); } while (0)
#define SPRINT(x) printf("%2u = sizeof(" #x ")\n", (unsigned int)sizeof(x))
int main(void)
{
/* Basic Types */
SPRINT(char);
SPRINT(unsigned char);
SPRINT(short);
SPRINT(unsigned short);
SPRINT(int);
SPRINT(unsigned int);
SPRINT(long);
SPRINT(unsigned long);
SPRINT(float);
SPRINT(double);
SPRINT(long double);
SPRINT(size_t);
SPRINT(ptrdiff_t);
SPRINT(time_t);
/* Fancy integers */
#if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG
SPRINT(long long);
SPRINT(unsigned long long);
#endif /* __STDC_VERSION__ || HAVE_LONG_LONG */
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
SPRINT(uintmax_t);
#ifdef INT8_MAX
SPRINT(int8_t);
#endif
#ifdef INT16_MAX
SPRINT(int16_t);
#endif
#ifdef INT32_MAX
SPRINT(int32_t);
#endif
#ifdef INT64_MAX
SPRINT(int64_t);
#endif
#ifdef INT128_MAX
SPRINT(int128_t);
#endif
SPRINT(int_least8_t);
SPRINT(int_least16_t);
SPRINT(int_least32_t);
SPRINT(int_least64_t);
SPRINT(int_fast8_t);
SPRINT(int_fast16_t);
SPRINT(int_fast32_t);
SPRINT(int_fast64_t);
SPRINT(uintptr_t);
#endif /* __STDC_VERSION__ || HAVE_INTTYPES_H */
/* Pointers */
SPRINT(void *);
SPRINT(char *);
SPRINT(short *);
SPRINT(int *);
SPRINT(long *);
SPRINT(float *);
SPRINT(double *);
/* Pointers to functions */
SPRINT(int (*)(void));
SPRINT(double (*)(void));
SPRINT(char *(*)(void));
/* Structures */
TPRINT(struct { char a; });
TPRINT(struct { short a; });
TPRINT(struct { int a; });
TPRINT(struct { long a; });
TPRINT(struct { float a; });
TPRINT(struct { double a; });
TPRINT(struct { char a; double b; });
TPRINT(struct { short a; double b; });
TPRINT(struct { long a; double b; });
TPRINT(struct { char a; char b; short c; });
TPRINT(struct { char a; char b; long c; });
TPRINT(struct { short a; short b; });
TPRINT(struct { char a[3]; char b[3]; });
TPRINT(struct { char a[3]; char b[3]; short c; });
TPRINT(struct { long double a; });
TPRINT(struct { char a; long double b; });
#if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG
TPRINT(struct { char a; long long b; });
#endif /* __STDC_VERSION__ */
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
TPRINT(struct { char a; uintmax_t b; });
#endif /* __STDC_VERSION__ || HAVE_INTTYPES_H */
return(0);
}
Não me lembro exatamente por que tive que mexer com __STDC_CONSTANT_MACROS
e SPRINT()
contra TPRINT()
, mas parecia ser isso que era necessário (em março de 2010) para tornar o código bilíngue.