Come si fa a sizeof lavoro per int tipi?
-
14-11-2019 - |
Domanda
Ho un piccolo programma che mette a confronto
(1) sizeof, (2) numeric_limits::cifre, (3) e i risultati di un ciclo
in uno sforzo per assicurarsi che essi segnalano la stessa cosa per quanto riguarda la dimensione di "int tipi" a qualsiasi implementazione di C++.Tuttavia, perché io non so i dettagli di sizeof, mi chiedo se è solo per il reporting di numeric_limits::cifre.Grazie
Soluzione
La maggior parte probabile sizeof()
sulla maggior parte dei compilatori fa sì che il compilatore sia il sembrare il tipo specificato (o il tipo dell'oggetto) nella sua tabella di tipo interno e inserire un letterale per la dimensione definita del tipo nel codice che genera. Ciò accadrebbe a tempo di compilazione , non runtime.
Per rispondere alla domanda nei commenti, non vi è alcun accesso definito dalla lingua agli interni del compilatore in C ++ (al di fuori di cose come sizeof()
stesso, ovviamente).L'unico linguaggio simile che conosco che ti consente di fare cose del genere è ADA, che fornisce Asis Per scrivere strumenti di analisi del codice indipendenti dal compilatore.
Altri suggerimenti
Il sizeof
l'operatore è un tempo di compilazione di costruire da cui il compilatore segnala la dimensione, in byte, di un'istanza di un certo tipo si occupano in memoria.
È difficile dare una generale "questo è come sizeof opere" risposta perché è specifico per ogni implementazione del compilatore.In generale se funziona calcolando la dimensione di ogni campo di un tipo e l'aggiunta di insieme mentre la contabilità per l'allineamento.
Per esempio, ecco una serie ragionevole di uscite [1]
struct S1 {
int field1;
int field2;
};
struct S2 {
int field1;
bool field2;
int field3;
}
sizeof(S1) == 8
sizeof(S2) == 12;
Il motivo per cui molti compilatori relazione la dimensione del S2
12 anziché 9 è che si deve tener conto dei problemi di allineamento e quindi inserire 3 byte per il divario tra field2
e field3
[1] Nota:Ho detto ragionevole non è garantita).C compila hanno un sacco di flessibilità in dimensioni ed è quasi impossibile stabilire le specifiche dimensioni senza conoscere il compilatore che si sta lavorando con
Non ci sono molti interni a sizeof
;È un operatore incorporato che riporta la dimensione del suo operando (un'espressione o un tipo) in byte.
Il tuo codice è piuttosto complesso - e l'utilizzo di typeid
mi lascia chiedersi ...
Ho un programma bilingue (scritto nel sottoinsieme C di C ++) che produce risposte come:
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; })
.
(Questo è stato prodotto da G ++ 4.6.0 su MacOS x 10.6.7 - una compilazione a 64 bit).Il codice che ho usato è:
#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);
}
.
Non ricordo esattamente il motivo per cui ho dovuto fare il pasticcio con __STDC_CONSTANT_MACROS
e SPRINT()
vs TPRINT()
, ma sembrava essere ciò che era necessario (indietro nel marzo 2010) per rendere il codice bilingue.