Как работает sizeof для типов int? - PullRequest
2 голосов
/ 17 мая 2011

У меня есть небольшая программа, которая сравнивает

(1) sizeof, (2) numeric_limits :: digits, (3) и результаты цикла

, чтобы убедиться,все они сообщают об одном и том же относительно размера типов int в любой реализации C ++.Однако, поскольку я не знаю о внутренностях sizeof, я должен задаться вопросом, просто ли он сообщает numeric_limits :: digits.Спасибо

Ответы [ 3 ]

3 голосов
/ 17 мая 2011

Скорее всего, sizeof() на большинстве компиляторов заставляет компилятор искать данный тип (или тип объекта) в своей внутренней таблице типов и вставлять литерал для определенного размера этого типа в код, который он генерирует. Это может произойти во время компиляции , а не во время выполнения.

Чтобы ответить на вопрос в комментариях, нет никакого определенного языка доступа к внутренним компонентам компилятора в C ++ (кроме таких вещей, какsizeof() сама, конечно).Единственный известный мне язык, позволяющий вам делать подобные вещи, - это Ada, которая предоставляет ASIS для написания независимых от компилятора инструментов анализа кода.

1 голос
/ 17 мая 2011

Оператор sizeof представляет собой конструкцию времени компиляции, с помощью которой компилятор сообщает размер в байтах, который экземпляр данного типа будет занимать в памяти.

Трудно дать общий ответ "это то, как работает sizeof", потому что он специфичен для каждой реализации компилятора.В general , хотя он работает путем вычисления размера каждого поля типа и сложения их вместе с учетом выравнивания.

Например, вот разумный набор выходных данных [1]

struct S1 {
  int field1;
  int field2;
};

struct S2 {
  int field1;
  bool field2;
  int field3;
}

sizeof(S1) == 8
sizeof(S2) == 12;

Причина, по которой многие компиляторы сообщают размер S2 как 12, а не 9, заключается в том, что он должен учитыватьпроблемы выравнивания и, следовательно, вставки 3 байта, чтобы восполнить разрыв между field2 и field3

[1] Примечание: я сказал, что разумно, а не гарантировано :).Компиляторы C обладают большой гибкостью в размерах, и практически невозможно указать конкретные размеры, не зная компилятор, с которым вы работаете

0 голосов
/ 17 мая 2011

Не так много внутренних органов для sizeof; это встроенный оператор, который сообщает размер своего операнда (выражения или типа) в байтах.

Ваш код довольно сложный - и использование typeid заставляет меня задуматься ...

У меня есть двуязычная программа (написанная в подмножестве C C ++), которая выдает ответы, такие как:

 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; })

(Это было сделано G ++ 4.6.0 на MacOS X 10.6.7 - 64-битная компиляция). Код, который я использовал:

#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);
}

Я не помню точно, почему я должен был связываться с __STDC_CONSTANT_MACROS и SPRINT() против TPRINT(), но, похоже, это было то, что было необходимо (еще в марте 2010 года), чтобы сделать код двуязычным. 1016 *

...