这是一个奇怪的情况。
我找到了这段代码。我在2011年3月的源代码中追溯到了一个提交。我旁边没有评论,但我相当肯定它是我在这个Q& A网站上看到的东西的改编。
namespace detail {
template <typename T, size_t N>
char (&SIZEOF_ARRAY_REQUIRES_ARRAY(T (&)[N]))[N];
}
#define SIZEOF(x) sizeof(detail::SIZEOF_ARRAY_REQUIRES_ARRAY_ARGUMENT(x))
以下是如何使用它:
int buffer[] = {1, 2, 3, 4, 5};
printf("Size of buffer: %u\n", SIZEOF(buffer)); // prints 5 instead of 8 (or 4)
我无法使用此模板/宏/这是常规项目。因此,我不能只是对它嗤之以鼻,用这个代替我所有的sizeof()
。我必须小心只在我懒惰的情况下使用它,并且想要获取我刚刚在堆栈上分配的缓冲区的大小。这就像字面上唯一有用的地方,也是我用过的唯一一个地方,而且我曾经只用过一次。
即使是现在也不清楚,或者我应该说,特别是现在,为什么这样做。这是这个问题的实际目的。为什么这个东西会起作用?它是如何工作的?这是 的模板是什么?这是一个功能吗? 这是什么魔法?
我打算现在删除这段代码,主要是因为它根本没有用处,但在我这样做之前,我必须深入了解它为什么会这样做。
答案 0 :(得分:2)
好吧,我有点想出答案。但不是在@WhozCraig先生之前。无论如何:
这里的声明是一个函数声明。没有功能实现。这样做的原因是因为sizeof
是一个特殊的小雪花,只有知道类型才能满足,当然函数声明给出sizeof
它需要的东西。
至于我们实际声明的功能,这会变得更加模糊,但据说它的返回类型是char [N]
的引用,我很抱歉但我不知道T (&)[N]
的意思,我认为这是对T [N]
的引用......这显然是这个函数的参数类型。好吧,最重要的是sizeof
最终会以某种方式获得char [N]或对这种类型的引用,这足以推断出你给原始宏的缓冲区的实际字节大小论点。
再看一下,奇怪的语法(我只能假设这些是引用类型)是为了阻止指针类型在这里经历的可能性并破坏我们所有的字节计数乐趣。
还有一个问题......我认为这会导致我的SIZEOF(buffer)
生成5
实际上错误。是的,5是该缓冲区的大小,但缓冲区上调用的 sizeof 实际上是它占用的实际字节数。因此,这必须是20!
更新:我刚刚在Xcode中测试了这个。对。 诽谤性!
int buffer[5];
std::cout << "omg" << SIZEOF(buffer) << std::endl;
输出:
omg5
很好,现在我必须让这项工作正常......哦,这不是太糟糕。
namespace detail {
template <typename T, size_t N>
- char (&SIZEOF_ARRAY_REQUIRES_ARRAY_ARG(T (&)[N]))[N];
+ char (&SIZEOF_ARRAY_REQUIRES_ARRAY_ARG(T (&)[N]))[N * sizeof(T)];
}
#define SIZEOF(x) sizeof(detail::SIZEOF_ARRAY_REQUIRES_ARRAY_ARG(x))
现在输出:
omg20