Как работи sizeof за типове int?

Имам малка програма, която сравнява

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

в опит да се уверите, че всички те отчитат едно и също нещо по отношение на размера на "типовете int" на всяка C++ реализация. Въпреки това, тъй като не знам за вътрешността на sizeof, трябва да се чудя дали той просто отчита numeric_limits::digits. Благодаря


person Community    schedule 16.05.2011    source източник
comment
Много дубликати: опитайте да търсите и след това, ако не намерите резултат, питайки, но това е задавано преди и тривиалното търсене как sizeof work дава няколко резултата. Гласувам за затваряне.   -  person David Rodríguez - dribeas    schedule 17.05.2011
comment
възможен дубликат на Как работи sizeof? Как мога да напиша свой собствен?   -  person David Rodríguez - dribeas    schedule 17.05.2011


Отговори (3)


Най-вероятно sizeof() на повечето компилатори кара компилатора да търси дадения тип (или типа на обекта) във вътрешната си таблица с типове и да вмъква литерал за дефинирания размер на този тип в кода, който генерира. Това ще се случи по време на компилиране, а не по време на изпълнение.

За да отговоря на въпроса в коментарите, няма дефиниран от език достъп до вътрешните части на компилатора в C++ (извън неща като самия sizeof(), разбира се). Единственият подобен език, който знам, който ви позволява да правите неща като това, е Ada, който предоставя ASIS за писане на независими от компилатора инструменти за анализ на код.

person T.E.D.    schedule 16.05.2011
comment
Случайно да знаете как мога ръчно да потърся стойността във вътрешната таблица с типове? Благодаря. - person ; 17.05.2011
comment
@Chris: за тип T, sizeof(T) дава този конкретен бит данни. По-малко педантичен отговор е не, освен ако вашият конкретен компилатор не ви позволява и тогава резултатът вероятно ще зависи от това какви флагове сте задали. - person Dennis Zickefoose; 17.05.2011
comment

Изглежда същият проблем като публикацията, която сте свързали: методът getView() не е вложен в класа.

Или кодът ви не показва нищо, което да го извика.

- person ; 17.05.2011

Операторът sizeof е конструкция по време на компилиране, чрез която компилаторът отчита размера в байтове, който екземпляр от дадения тип ще заема в паметта.

Трудно е да се даде общ отговор „ето как работи sizeof“, защото той е специфичен за всяка реализация на компилатор. Като общо работи, като изчислява размера на всяко поле от даден тип и ги събира заедно, като отчита подравняването.

Ето например разумен набор от резултати [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 компилациите имат голяма гъвкавост по отношение на размерите и е почти невъзможно да се заявят подробности за размерите, без да се знае компилаторът, с който работите

person JaredPar    schedule 16.05.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 г.), за да направя кода двуезичен.

person Jonathan Leffler    schedule 16.05.2011
comment
Трябва да отбележите обаче, че това е изход от 64-битов компютър. Дългият int на 32-битов е 4 байта вместо 8 бита, а дългите двойки са само 12 байта на 32-битова система и често указателите са 4 байта вместо 8 байта. - person DipSwitch; 17.05.2011
comment
@DipSwitch: да, това е 64-битов компилатор. Отговорите по своята същност са специфични за платформата. В Windows 64, например, sizeof(long) == 4 все още, въпреки че на повечето Unix 64-битови машини, sizeof(long) == 8. Това е разликата между системите ILP32, LP64, ILP64, LLP64. - person Jonathan Leffler; 17.05.2011