'复杂'的默认类型在C.

时间:2017-01-13 15:32:56

标签: c gcc

根据文档,我已阅读C99及更高版本支持float complexdouble complexlong double complex作为复杂类型。但是,使用gcc -Wall -Wextra时,此代码会在没有警告的情况下编译。

#include <stdio.h>
#include <complex.h>

int main() {
    int a, b, c, d;
    float re, im;

    scanf("%d %d", &a, &b);
    complex matrix[a][b]; /* <------ */

    for(c=0; c<a; c++) {
        for(d=0; d<b; d++) {
            scanf("%f%fi", &re, &im);
            matrix[c][d] = re + im * I;
        }
    }

    for(c=0; c<a; c++) {
        for(d=0; d<b; d++) {
            printf("%.2f%+.2fi ", creal(matrix[c][d]), cimag(matrix[c][d]));
        }
        printf("\n");
    }
}
  • 这是有效的C还是gcc奇怪?
  • complex matrix[a][b];给我们的是哪种类型?

如果你用clang编译它,你会得到:

  

main.c:9:5:警告:简单&#39; _Complex&#39;需要一个类型说明符;   假设&#39; _Complex double&#39;

请参阅clang output

gcc bug现已在this link报告。 (不是我。)

2 个答案:

答案 0 :(得分:4)

根据C99(ISO 9899:1999):

  • complex是一个宏(在<complex.h>中定义),可扩展为_Complex(7.3.1 / 2)。

  • _Complex是类型说明符(就像intdoubleunsigned等)(6.7.2 / 1)。

6.7.2 / 2:

  

<强>约束

     

每个声明中的声明说明符中应至少提供一个类型说明符,并在每个结构声明和类型名称的说明符限定符列表中指定。每个类型说明符列表应为以下集合之一(用逗号分隔,当一行上有多个集合时);类型说明符可以按任何顺序出现,可能与其他声明说明符混合。

     
      
  • [...]

  •   
  • float _Complex

  •   
  • double _Complex
  •   
  • long double _Complex
  •   

这些是包含_Complex的唯一类型说明符集,这意味着不允许complex floatdoublelong double。{ / p>

此外:

  

5.1.1.3诊断

     

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

由于使用complex all本身就是违反约束,因此需要编译器警告或错误。如果您没有收到gcc -std=c99 -pedantic的警告,那么您在gcc中发现了一个错误。

答案 1 :(得分:3)

如果省略它,GCC和Clang看起来都假定类型为double(如您的示例所示)。 Clang产生:

 warning: plain '_Complex' requires a type specifier; assuming '_Complex double'
    complex matrix[a][b];
    ^
            double
/usr/include/complex.h:39:18: note: expanded from macro 'complex'
#define complex         _Complex
                        ^

虽然海湾合作委员会做同样的事情(假设为double),但它似乎并不警告它。

无论编译器诊断如何,扩展到complex的{​​{1}}本身不是类型,而只是类型说明符。因此,您需要指定类型。