Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default types for 'complex' in C

Tags:

c

gcc

According the docs I have read C99 and later support float complex, double complex and long double complex as complex types. However this code compiles without warning when using 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");
    }
}
  • Is this valid C or is it a gcc oddity?
  • What type is complex matrix[a][b]; giving us?

If you compile it with clang you get:

main.c:9:5: warning: plain '_Complex' requires a type specifier; assuming '_Complex double'

See the clang output.


gcc bug now reported at this link. (Not by me.)

like image 517
graffe Avatar asked Jan 13 '17 15:01

graffe


2 Answers

According to C99 (ISO 9899:1999):

  • complex is a macro (defined in <complex.h>) that expands to _Complex (7.3.1/2).

  • _Complex is a type specifier (just like int, double, unsigned, etc) (6.7.2/1).

6.7.2/2:

Constraints

At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each struct declaration and type name. Each list of type specifiers shall be one of the following sets (delimited by commas, when there is more than one set on a line); the type specifiers may occur in any order, possibly intermixed with the other declaration specifiers.

  • [...]

  • float _Complex

  • double _Complex
  • long double _Complex

These are the only type specifier sets that contain _Complex, which means that complex without float, double, or long double is not allowed.

Furthermore:

5.1.1.3 Diagnostics

1 A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined.

Since using complex all by itself is a constraint violation, a compiler warning or error is required. If you don't get a warning with gcc -std=c99 -pedantic, then you've found a bug in gcc.

like image 155
melpomene Avatar answered Oct 31 '22 11:10

melpomene


Looks like both GCC and Clang assume the type to be double if you omit it (like in your example). Clang produces:

 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
                        ^

While does GCC does the same (assuming double), it doesn't seem to warn it.

Regardless of compiler diagnostics, complex which expands to _Complex is not a type by itself but only a type specifier. So, you need to specify the type.

like image 4
P.P Avatar answered Oct 31 '22 11:10

P.P