Как работает sizeof? Как я могу написать свою?

Я знаю С++ и знаю функцию sizeof, но мне нужно написать свою собственную функцию sizeof, поэтому, пожалуйста, объясните, как она работает точно? Что он делает с параметром?

Ответ 1

Вы не предоставили сколько-нибудь значимых подробностей о том, что именно вы хотите сделать, поэтому трудно понять, что вам нужно.

Вы можете "обернуть" sizeof своей собственной функцией шаблона, например,

template <typename T> size_t my_sizeof() {
  return sizeof(T);
}

а затем использовать его как

size_t s = my_sizeof<int>();

Время от времени можно встретить запрос на реализацию функции sizeof-like без использования sizeof. Подобные запросы не имеют никакого практического смысла, но иногда используются как домашние задания. Вероятно, это можно сделать следующим образом

template <typename T> size_t my_sizeof() {
  T t;
  return (char *) (&t + 1) - (char *) &t;
}

что потребовало бы конструирования по умолчанию T. Менее ограничивающее, но формально незаконное решение (взлом) будет что-то вроде

template <typename T> size_t my_sizeof() {
  return (char *) ((T *) NULL + 1) - (char *) (T *) NULL;
}

Вышеуказанные реализации реализуют на основе типа sizeof.

Попытка эмулировать функциональность на основе значений sizeof может выглядеть следующим образом

template <typename T> size_t my_sizeof(const T& obj) { 
  return my_sizeof<T>();
}

но это не будет даже удаленно эквивалентно встроенному sizeof, хотя бы потому, что встроенный sizeof не оценивает свой аргумент.

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

В любом случае это все, конечно, полностью лишено какой-либо практической ценности. Просто используйте sizeof, когда хотите узнать размер.

Ответ 2

sizeof является встроенным оператором компилятора. Компилятор оценивается во время компиляции компилятором, и за ним нет кода времени выполнения. Вы не можете написать свой собственный.

Спрашивая, это похоже на вопрос, как написать свою собственную версию return.

Ответ 3

Не переносимый способ написать собственную функцию sizeof() состоит в том, чтобы воспользоваться тем, как часто хранятся переменные на основе стека в памяти:

#include <iostream>
using namespace std;

template <typename T>
int mysizeof(T)
{
  T temp1;
  T temp2;

  return (int)&temp1 - (int)&temp2;
}

int main()
{
  cout << "sizeof mysizeof" << endl;

  char c = 0; short s = 0; int i = 0; long l = 0;
  float f = 0; double d = 0; long double ld = 0;

  cout << "char: " << mysizeof(c) << endl;
  cout << "short: " << mysizeof(s) << endl;
  cout << "int: " << mysizeof(i) << endl;
  cout << "long: " << mysizeof(l) << endl;
  cout << "float: " << mysizeof(f) << endl;
  cout << "double: " << mysizeof(d) << endl;
  cout << "long double: " << mysizeof(ld) << endl;
}

Посмотрите в действии.
0-параметрическая версия.
Версия, которая использует один массив вместо двух переменных.

Предупреждение: Это была забавная головоломка, но вы никогда не должны использовать ее в реальном коде. sizeof гарантированно работает. Это не. Просто потому, что он работает над этой версией этого компилятора для этой платформы, это не значит, что он будет работать для любого другого.

Реальный оператор использует часть компилятора. Sizeof знает, насколько велик каждый тип переменной, потому что он должен знать. Если компилятор не знает, насколько велик каждый тип, он не сможет выложить вашу программу в памяти.

Изменить: обратите внимание, что все эти ошибочные примеры основаны на исходном операторе sizeof. Он использовался для размещения переменных стека, а также для создания и индексирования переменных массива.

Ответ 4

Как уже говорилось, оператор не является функцией, но дополнительно является одним из операторов, для которых не допускается перегрузка оператора:

Bjarne Stroustrup С++ Стиль и техника Часто задаваемые вопросы: Почему я не могу перегрузить точку,::, sizeof и т.д.?

Я не могу думать ни о какой мыслимой причине, почему вы бы хотели перегрузить это в любом случае. Если у вас есть класс, для которого требуется информация о размере, отличная от того, что требуется sizeof, просто добавьте функцию-член для предоставления этой информации; как, например, в std::string:size(), который возвращает длину строки, управляемой объектом, а не размер объекта, который семантически отличается; вы не хотите обезьяны с семантикой sizeof!

Ответ 5

sizeof - это оператор С++, который дает количество байтов в представлении объекта его операнда. Результат sizeof представляет собой константу, определенную реализацией типа size_t, но должен соответствовать требованиям, изложенным в С++ Standard 5.3.3. Вы можете написать свои собственные черты типа, которые будут работать подобно встроенному оператору sizeof.

template<typename T> struct get_sizeof;

template<> struct get_sizeof<char>          { static const size_t value = 1; };
template<> struct get_sizeof<unsigned char> { static const size_t value = 1; };
template<> struct get_sizeof<int>           { static const size_t value = 4; };
template<> struct get_sizeof<long>          { static const size_t value = 4; };
// etc.

...
// sample of use
static const size_t size = get_sizeof<int>::value;
char x[get_sizeof<int>::value];

Но это не имеет смысла, поскольку только создатели компилятора знают фактические значения value для реализации.

Ответ 6

sizeof не является функцией, и вы не можете написать свою собственную версию. Компилятор выдает тип аргумента (если он уже не является типом), а затем заменяет выражение целой константой.

Ответ 7

Я видел это сообщение при поиске способа получить ту же функциональность, что и оператор sizeof. Оказалось, что я реализовал функцию bit_sizeof(), которая очень похожа на оператор sizeof, но вместо этого возвращает число бит данного типа. Я применил глобальную функцию шаблона, например:

#include <limits.h>   //For CHAR_BIT

//Global function bit_sizeof()
template<typename TSizeOfType>
constexpr uint32_t bit_sizeof(TSizeOfType)
{
   return (sizeof(TSizeOfType) * CHAR_BIT);
}

Эта функция требует использования стандарта С++ 11, так как использует ключевое слово constexpr. Без ключевого слова constexpr функция будет компилироваться еще. Но компилятор не может правильно оптимизировать и поставить вызов функции на каждом сайте вызова с использованием функции bit_sizeof. С использованием constexpr вся функция оценивается константой, которая, насколько мне известно, должна быть точно эквивалентна тому, как работает оператор sizeof? Поправьте меня, если я ошибаюсь. При использовании я вызываю функцию, подобную этой, с добавленным парантесом после типа:

uint32_t uiBitsInType = bit_sizeof(char());

Эта функция может быть полезна при создании бит-масок, например:

uint32_t uiMask = (((uint32_t(0x1) << bit_sizeof(char())) - 0x1) << bit_sizeof(char()));

Что может быть более читаемым, чем это:

uint32_t uiMask2 = (((uint32_t(0x1) << (sizeof(char) * 0x8)) - 0x1) << (sizeof(char) * 0x8));

Лично у меня есть и другие функции для этой функции.

Ответ 8

Если он хочет написать свой собственный размер, ему просто нужно взять исходный код компилятора на С++ и продолжить. Источник также покажет, как sizeof может быть реализован.

Ответ 9

sizeof оценивается во время компиляции (Boost и Loki). Поэтому, я думаю, невозможно написать функцию sizeof - complain для динамически распределенного буфера.

Ответ 10

sizeof не является функцией. Это оператор в C. Мы можем реализовать свою функциональность, как показано ниже.

#include <stdio.h>

#define mysizeof(X)  \

           ({                    \
                  __typeof(X) x;  \
                  (char *) (&x+1) - (char*) (&x); \
           })
int main()
{

     struct sample
     {
         int a;float b; char c;
     };

     printf("%d", mysizeof(struct sample));
     return 0;
}

Ответ: 12