[英]What is happening with this code?
我正在尝试使用Android AOSP键盘源作为模型来开发Android键盘。 有很多JNI代码,我的C ++有点生锈,对于宏NELEMS
的以下定义,我遇到了麻烦:
// Disclaimer: You will see a compile error if you use this macro against a variable-length array.
// Sorry for the inconvenience. It isn't supported.
template <typename T, int N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define NELEMS(x) (sizeof(ArraySizeHelper(x)))
当我尝试编译时,此代码的第二行(在#define
上方)亮起并显示错误:
引用变量的声明需要一个初始化程序
该错误消息对我来说很有意义。 AOSP代码没有。 ArraySizeHelper
符号在AOSP代码或make文件中的其他位置都没有出现(也就是说,据我所知,它不是其他内容的宏)。
从宏的名称,我猜想它应该对数组中元素的数量求值。 据我所知,通常的方法是:
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
所以我想知道这里是否还有其他事情发生。
我将很高兴对此代码进行解释并提供有关如何处理编译错误的指南。
编辑:我正在通过Android Studio 1.3 RC 3,Android NDK r10e和Gradle 2.5进行编译。 编译使用各种工具链(如本Android文档中所述 )。 奇怪的是,以上代码现在可以正确编译并执行(也许总是如此)。 但是,Android Studio仍然在该行显示错误。 每次使用NELEMS
也会显示错误:
宏替换后发生错误:参数过多,预期为0
我现在认为这是IDE代码分析错误,而不是编译器或编码问题。 我最初的问题是关于代码本身的,所以我将此线程标记为已回答。 我将打开另一个有关似乎是IDE问题的问题。 感谢大家的解释!
该代码的目的是安全地获得可以在编译时使用的数组大小,例如,作为新的原始(非动态)数组的大小。
简单的定义
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
…是不安全的,因为您可以将指针传递给它,并返回无用的大小。
所以您拥有的代码
template <typename T, int N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define NELEMS(x) (sizeof(ArraySizeHelper(x)))
…使用模板参数推导来找到大小,并使用引用数组返回类型将大小报告为编译时间常数。 如果不是(1)在C ++ 11及以后关于传递引用的愚蠢措辞,我们现在可以使用constexpr
进行相同的操作。 las,我们可能要等到C ++ 17才能完全避免使用宏,以完成获取编译时间数组大小的简单任务。
我无法重现该问题; 以下代码:
template <typename T, int N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define NELEMS(x) (sizeof(ArraySizeHelper(x)))
#include <iostream>
auto main() -> int
{
using namespace std;
int x[42];
cout << NELEMS( x ) << endl;
}
可以与Visual C ++ 2015和MinGW-64 g ++ 5.1.0很好地编译。
1) C ++ 14§5.19/ 2“ 条件表达式 e
是核心常量表达式,除非按照抽象机(1.9)的规则对e
求值将对以下表达式之一求值:[…] —引用引用的变量或数据成员的id表达式 ,除非引用具有先前的初始化,并且-用常数表达式初始化,或者-它是对象的非静态数据成员,其生存期始于e
评估;”
这个:
template <typename T, int N>
char (&ArraySizeHelper(T (&array)[N]))[N];
声明了一个名为函数ArraySizeHelper
其花费的数组的引用N
T
的named array
并返回参照的数组char[N]
没有给出定义。
sizeof()
不需要定义函数-它的操作数未评估。 它仅对类型进行操作:因此,如果x
的类型为T[N]
,则sizeof(ArrayHelper(x))
结果为sizeof(char[N])
(否则将不进行编译)。
这也是一种极其复杂的书写方式:
template <typename T, size_t N>
constexpr size_t array_size(T (&)[N]) { return N; }
这要容易得多。 并且不需要宏。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.