sizeof如何工作?我怎么写自己的?

时间:2010-06-22 16:08:42

标签: c++

我了解C ++并且知道函数sizeof本身,但我需要编写自己的sizeof函数,所以请解释它是如何工作的?它如何处理参数?

10 个答案:

答案 0 :(得分:31)

sizeof是一个编译器内置运算符。它在编译时由编译器进行评估,并且后面没有运行时代码。你不能自己写。

询问这类似于询问您如何编写自己的return版本。

答案 1 :(得分:26)

您没有提供有关您想要做什么的任何有意义的详细信息,因此很难弄清楚您需要什么。

您可以通过自己的模板函数“包裹”sizeof,如

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

然后将其用作

size_t s = my_sizeof<int>();

有时可能会遇到使用sizeof实现类似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

最后,这些实现都不会像内置sizeof那样产生整数常量表达式(ICE)。在当前版本的语言中无法以这种方式生成ICE。

无论如何,这一切当然完全没有任何实际价值。如果您想知道尺寸,请使用sizeof

答案 2 :(得分:7)

编写自己的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;
}

See it in action.
A 0-parameter version.
A version that uses one array instead of two variables.

警告:这是一个有趣的谜题,但你不应该在实际代码中使用它。 sizeof保证有效。这不是。仅仅因为它适用于此平台的此版本编译器并不意味着它适用于任何其他版本。

真实运算符利用作为编译器的一部分。 Sizeof知道每种类型的变量有多大,因为它必须知道。如果编译器不知道每种类型有多大,它将无法将程序放在内存中。

编辑:请注意,所有这些有缺陷的示例都依赖于原始sizeof运算符。它用于分隔堆栈变量,以及创建和索引数组变量。

答案 3 :(得分:4)

正如已经说过的那样,它不是一个函数,而是一个不允许运算符重载的运算符之一:

Bjarne Stroustrup's C++ Style and Technique FAQ: Why can't I overload dot, ::, sizeof, etc.?

在任何情况下,我都无法想到为什么你想要重载它。如果您的类的大小信息不是sizeof产生的大小信息,那么只需添加一个成员函数来提供该信息;例如在std::string:size()中,它返回由对象管理的字符串的长度,而不是在语义上不同的对象的大小;你不想使用sizeof的语义来呀!

答案 4 :(得分:2)

sizeof是一个C ++运算符,它产生其操作数的对象表示中的字节数。 sizeof的结果是类型size_t的实现定义常量,但应满足C ++标准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

答案 5 :(得分:1)

sizeof不是函数,您无法编写自己的版本。编译器计算出参数的类型(除非它已经是一个类型),然后用整数常量替换表达式。

答案 6 :(得分:1)

我在搜索获取与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);
}

此函数需要使用c ++ 11标准,因为它使用关键字constexpr。没有关键字constexpr,该函数将仍然编译。但是编译器可能无法正确优化并在使用bit_sizeof函数的每个调用站点进行函数调用。使用constexpr,整个函数求值为常量,据我所知,它应该与sizeof运算符的工作方式完全相同?如果我错了,请纠正我。在使用中,我调用这样的函数,在类型后添加了一个parantesis:

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

我个人也有此功能的其他用途。

答案 7 :(得分:0)

如果他想编写自己的sizeof,他只需要获取C ++编译器的源代码并继续。该来源还将展示如何实施sizeof。

答案 8 :(得分:0)

sizeof在编译时进行评估(BoostLoki使用它)。因此,我认为,不可能为动态分配的缓冲区编写sizeof - complain函数。

答案 9 :(得分:0)

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