标量初始化程序代码中的多余元素使用gcc但不使用g ++进行编译

时间:2014-07-28 21:07:36

标签: c++ c gcc compiler-errors g++

只是好奇为什么这个代码(显然是错的)使用gcc编译,但是使用g ++的代码却没有。

int main()
{
    char *foo = {"bar", "fred", "bob"};

    return 0;
}

gcc发出此警告,但仍然编译并生成二进制文件:

  

gcc -o x x.c

     

x.c:在函数'main'中:x.c:3:5:警告:多余   标量初始值设定项中的元素[默认启用] x.c:3:5:警告:   (接近初始化'foo')[默认启用] x.c:3:5:警告:   标量初始值设定项中的多余元素[默认启用] x.c:3:5:   警告:(接近初始化'foo')[默认启用]

     

ls -l x

     

-rwxr-xr-x 1 overdrive overdrive 6593 7月28日21:51 x

g ++给出了这个错误,没有任何二进制文件作为输出:

  

g ++ -o y y.cpp

     

y.cpp:在函数'int main()'中:   y.cpp:3:38:错误:标量对象'foo'在初始值设定项中需要一个元素

     

ls -l y

     

ls:无法访问y:没有这样的文件或目录

我使用的gcc和g ++版本是:

  

g ++ --version
  g ++(Debian 4.7.2-5)4.7.2   版权所有(C)2012 Free Software Foundation,Inc。   这是免费软件;查看复制条件的来源。没有   保证;甚至不适用于适销性或特定用途的适用性。

有没有什么好的理由可以用gcc编译而不是用g ++编译?或者它显然是一个错误?

2 个答案:

答案 0 :(得分:8)

是的,有一个很好的理由使它成为C ++中的一个难题,即使是历史上在C语言中接受的实现:

template <typename T, int = sizeof(T{1,2,3,4})>
void f();

template <typename T>
void f(...) { }

int main() { f<int>(); }

这是一个有效的C ++程序。编译器不得拒绝这一点,抱怨模糊调用或链接器错误抱怨第一个重载未定义:C ++标准要求f<int>()调用第二个重载,因为第一个重载有替换错误。

考虑到这一点,实现面临两个选择:它们可以始终拒绝多余的初始化者,或者他们可以仔细确定标准要求拒绝它们的上下文,以及在哪些上下文中实现可以继续允许它们。 GCC和clang开发人员选择不断拒绝它们,这更容易实现。

C在编译时没有任何确定表达式有效性的工具,因此对于C,这种扩展无法使有效程序被拒绝。

答案 1 :(得分:2)

根据C 2011标准

  

标量的初始化程序应该是单个表达式,可选   括在括号中

动词应表示编译器应发出诊断消息:)

所以它是编译器的一个特性或错误。:)

根据C标准

  

1符合要求的实施应至少产生一种诊断   消息(以实现定义的方式标识)如果a   预处理翻译单元或翻译单元包含一个   违反任何语法规则或约束,即使行为是   也明确指定为未定义或实现定义的