问题与解析
// 下一句编译不过
// 错误为:initializer element is not a compile-time constant
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
@implementation SomeClass
@end
我们从这个错误提示本身入手:
- 什么是
initializer element - 什么是
compile-time constant
我们上面这句代码做的事情是初始化一个变量的过程,initializer element就是 [NSMutableDictionary dictionary]
compile-time constant,从字面意思上来看是“编译时的常量”,大致是说在编译期间认为的常量的意思
那么,什么东西才可以叫做compile-time constant
经过一顿谷歌搜索后,发现该问题要追溯到C语言中,因为Objective C是C语言的一个超集,所以C语言中的错误照样也会发生在Objective C写的程序中
在C语言标准-C99中有如下内容:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
All objects with static storage duration shall be initialized (set to their initial values) before program startup.
An object whose identifier is declared with external or internal linkage, or with the storage-class specifier static has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
再结合Understanding static storage class in C中关于全局变量的说明,可以知道上面声明的**dict是符合static storage duration的**
所以,初始化dict时,initializer element必须是constant expression
那什么是constant expression?
C语言标准中当然也有定义了--参考C99的Constant expressions部分,下面节选其中的一部分
A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.
Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.95)
显然,[NSMutableDictionary dictionary]肯定不是constant expression了
总结
其实该问题本身并不是那么重要,最重要的我认为是上面所查到的各种资料以对基础知识的理解(其实就是对C语言中static、const标识符、constant expression等概念的理解)
就这么个看起来很简单的问题,我其实断断续续查了好几天的资料。深入分析问题,才会发现自己对C的理解很肤浅。同时查找问题的过程也再次让我体会到:
- 学好英语的重要性,该问题及其相关问题的讨论主要集中在stackoverflow等英文技术论坛中
- 举个例子,像constant expression这种,在C或者其他语言中都是一个专业术语,如果翻译为中文,在中文技术文章可能就很难给读者留下印象并深入学习
- 一些看上去好像很想当然的问题,背后原理可能还是挺复杂的。但不论多么复杂,只要对基础概念理解好,就会大幅提高解决问题的可能。举例说明
我们使用Xcode(13.4.1)编译如下代码
int a = 10;
int b = a + 1;
int b一行会报"initializer element is not a compile-time constant"的错
而略微修改一下就编译成功了
const int a = 10;
int b = a + 1;
请问为什么?
你可能会自然地想到,因为const会让a以及a+1变为constant expression
但在我看来,这并不是正确答案
我来证明下为什么不正确
如果将编译器换成GCC 7.4.0,则会编译失败。而改成Xcode自带的Clang编译器则是成功的
而且,C99中,确实不会将const修饰的对象认为是constant expression的
所以,原因可能是Objective C以及其编译器做了额外的工作以支持