繁体   English   中英

此代码是怎么回事?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM