这段代码发生了什么
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]))
所以我想知道这里是否发生了什么。
我希望能解释一下这段代码应该做什么,并指导一下如何处理编译错误。
EDIT:我通过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)))
白马王子;使用模板参数推导查找大小,并使用引用到数组的返回类型将大小报告为编译时常量。如果不是c++ 11中(1)的愚蠢措辞,我们现在可以对constexpr
做同样的事情。唉,我们可能要等到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 - 64g++ 5.1.0下都能很好地编译。
<一口>1) c++ 14§5.19/2 “A 条件表达式 e
是核心常量表达式,除非e
求值,遵循[…] -一个id-expression,它指向引用类型的变量或数据成员,除非引用之前有初始化,并且两者都有-用常量表达式或初始化-它是一个对象的非静态数据成员,其生命周期开始于e
;”一口>
This:
template <typename T, int N>
char (&ArraySizeHelper(T (&array)[N]))[N];
声明了一个名为ArraySizeHelper
的函数,它接受一个名为N
的数组的引用,T
名为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; }
更容易理解。并且不需要宏
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 这C++代码中发生了什么C++(指数函数)
- 哪种方式更快?究竟发生了什么,我们没有看到什么?
- 从"LLONG_MAX 秒"构造 std::chrono::毫秒变量时发生了什么?
- 这个片段中关于 n 在 pc[i] 中的表示发生了什么
- istringstream,num1 和 num2 在这里发生了什么?
- 究竟发生了什么,我们需要在 c++ 中双重调度/访客
- 我是否能够确定在部署一个程序后发生了什么,我在数组末尾写入?
- 这个阶乘程序内部发生了什么?
- C++ - *(int**) 地址?这里发生了什么?
- C++用用户输入在循环中填充 char 数组:输入整个字符串时到底发生了什么?
- 让对象知道它创建的 show 函数中发生了什么
- 这里的矢量数组发生了什么?
- 增加顶级常量指针时发生了什么
- 当另一端将其关闭时,插座发生了什么
- C :我堆栈顶部发生了什么
- 此递归中发生了什么?我需要仅使用递归/无循环来计算和备份
- 这个 std::vector 构造函数中发生了什么
- 编译器认为 int 是一个字符串.发生了什么事情
- 无法运行简单的 std::async 和 std::future 测试程序。错误:"has initializer but incomplete type."发生了什么?