读《C++ Primer》之零长度数组

C++ Primer

C++ Primer

工作以来,我用过不少的编程语言,它们分别用在不同的技术场景中,比如用在企业应用中后台逻辑的 Java,用于数据库存储过程的 PL/SQL。但一直遗憾的是,没有工作机会采用 C/C++。日子一久,在学校里积攒的那点儿三脚猫 C++ 功夫就荒废了。这些系统级编程语言使用经验的缺失,使得我在理解底层问题时感到非常困难。自2013年初以来,我在空闲时间通过重新阅读《C++ Primer》一书,弥补遗忘的 C++ 知识,希望能够补上这个短板。本篇博客即是我在阅读时的思考,既做为自己的读书笔记,也供其他人参考和批判。

在书的4.3.1章节“创建动态数组”中,对比数组变量和动态数组时,提到:

C++虽然不允许定义长度为0的数组变量,但明确指出,调用new动态创建长度为0的数组是合法的。

前半句话引起了我的好奇,根据使用 Java 的经验,我知道这是可行的。所以,我验证一下。

int main() {
char a[0];
return sizeof(a);
}

使用以下命令,发现一切顺利。

g++ array_test.cpp

于是,我怀疑书上的说法是不是过时了,于是我指明采用 C++ 98 标准,但是仍然没有问题。

g++ -std=c++98 array_test.cpp

这让我大为惊奇,怎么这么一本经典的书会犯错呢?于是进一步探索,找到了一个同样的问题:“What happens if I define a 0-size array in C/C++?”。

从中了解到 C 标准(ISO/IEC 9899:2011)中要求数组变量长度是必须要大于0,见 “6.7.6.2 Array declarators”。同时,我从 C++ 标准(ISO/IEC 14882:2011)也找到了类似的表述,详见“8.3.4 Arrays”:

If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.

GCC

GCC

可是为什么编译通过了呢?因为这是编译器自行做了扩展,见 GCC 文档Arrays of Length Zero。注意,这是说对 C 标准做了扩展,并没有指明是 C++,我尝试寻找对此的扩展说明,但没有找到。

Zero-length arrays are allowed in GNU C. They are very useful as the last element of a structure that is really a header for a variable-length object:

我留意到在上面的链接里,提示了使用 -pedantic 参数进行编译,那么这个参数可以做什么呢?

Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some otherprograms that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.

于是,加上上面的参数,编译过程中看到有警告信息输出:

array_test.cpp: In function ‘int main()’:
array_test.cpp:2:13: error: ISO C++ forbids zero-size array ‘a’ [-pedantic]

但是,这只是警告,仍可以得到可执行文件,那么如何更严格?当出现上述现象时,阻止编译以及接下来的汇编和链接呢?答案就是使用 pedantic-errors,手册中是这么介绍它的:

Like -pedantic, except that errors are produced rather than warnings.

现在的命令如下,严格采用 C++11 标准,发现违反标准时,抛出错误,中断编译。

g++ -std=c++11 -pedantic-errors array_test.cpp

Leave a comment

Your comment