在编译一个相当简单的c ++ 11程序时,gcc和clang之间的结果不同

时间:2013-12-08 11:37:16

标签: c++ gcc c++11 clang

我试图了解这个简单的C ++ 11程序输出中gcc与clang所暴露的不同行为是否是由于clang(Xcode 5.0.2,OS X 10.8.5)中的错误引起的。代码如下:

#include <iostream>

int main() {


    int matrix[][3]{{1,2,3}, {4,5,6}, {7,8,9}};
    auto dyn_matrix = new int[3][3]{{1,2,3}, {4,5,6}, {7,8,9}};

    std::cout << matrix[0][1] << std::endl;
    std::cout << dyn_matrix[0][1] << std::endl;

    return 0;   
}

如图所示,我正在尝试使用统一初始化来初始化大小为3x3的匿名(resp。命名)多维数组。当使用MacPorts的gcc 4.7进行编译时,可以获得预期的输出:

$g++-mp-4.7 -std=c++11 dyn_matrix.cpp -o dyn_matrix 
$ ./dyn_matrix
2
2
$

相反,如果使用clang,则输出显示为:

$ clang++ -std=c++11 -stdlib=libc++ dyn_matrix.cpp -o dyn_matrix_clang
$ ./dyn_matrix_clang 
2
4
$  

在这种情况下,结果(显然)是错误的。 clang --version报告:

Apple LLVM version 5.0 (clang-500.2.75) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

谁应该受到责备?我,gcc还是clang?

更新2013年12月11日:该错误应该已在r196995中修复。不幸的是,我们仍然不知道Apple更新Xcode附带的clang版本需要多长时间。

更新2013年12月9日:我提交了有关LLVM bugzilla平台的错误报告。它确实被认为是一个错误,目前正在审核补丁,请参阅http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20131209/095099.html

感谢。

1 个答案:

答案 0 :(得分:20)

更新:感谢Faisal Vali和Richard Smith,这个错误已在Clang ToT中得到纠正;请参阅提交引入的test file


根据§8.5.1[dcl.init.aggr] ,看来Clang错了:

  

11 /大括号可以在初始化列表中省略,如下所示。如果 initializer-list 以左括号开头,则后续的以逗号分隔的 initializer-clauses 列表初始化子集合的成员;有没有比成员更多的初始化程序条款是错误的。但是,如果子集合的初始化列表不以左括号开头,那么列表中只有足够的 initializer-clauses 来初始化成员子聚集;剩余的 initializer-clause 用于初始化当前子聚合为成员的聚合的下一个成员。 [示例:

float y[4][3] = {
    { 1, 3, 5 },
    { 2, 4, 6 },
    { 3, 5, 7 },
};
     

是一个完全支撑的初始化:1,3和5初始化数组y[0]的第一行,即y[0][0]y[0][1]y[0][2]。同样,接下来的两行初始化y[1]y[2]。初始化程序提前结束,因此初始化y[3]个元素,就像使用float()形式的表达式显式初始化一样,即使用0.0进行初始化。在以下示例中, initializer-list 中的大括号被省略;但初始化列表与上例中完全支撑的初始化列表具有相同的效果,

float y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5, 7
};
     

y的初始化程序以左括号开头,但y[0]的初始化程序没有,因此使用列表中的三个元素。同样,接下来的三个是y[1]y[2]连续拍摄的。 - 结束示例]

我认为适用于§5.3.4[expr.new]

  

15 / A new-expression 创建一个T类型的对象,按如下方式初始化该对象:

     
      
  • 如果省略 new-initializer ,则默认初始化对象(§8.5);如果没有执行初始化,则该对象具有不确定的值。
  •   
  • 否则, new-initializer 将根据§8.5的初始化规则进行解释,以便直接初始化。
  •