Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the integer literal suffix 'i' in C?

Tags:

c

To my surprise, this code compiles with GCC 11.4.0 and i becomes 0:

#include <stdio.h>

int     main( int argc, char *argv[] )
{
        int i = 1i;
        printf( "i = %d\n", i );
        return 0;
}

I tried googling for the suffix i, but without success. In every description I've found only the usual ones are mentioned (e.g., in the answers to that Stack Overflow question).

I've also tried with all lower characters and other integer values and found that it's the same behaviour with j, and the value of my variable was always 0. With other suffixes like a, b, etc., it wouldn't compile.

So what is it that I've been stumbled upon? And is there a way to prevent GCC from compiling that or at least have some kind of diagnostics? In the 'real-world source' this happened because of a simple typo and of course resulted in run time errors.

like image 249
Ingo Leonhardt Avatar asked Sep 12 '25 20:09

Ingo Leonhardt


2 Answers

From GNU docs:

The simple way to write an imaginary-number constant is to attach the suffix ‘i’ or ‘I’, or ‘j’ or ‘J’, to an integer or floating-point constant. For example, 2.5fi has type _Complex float and 3i has type _Complex int. The four alternative suffix letters are all equivalent...Standard C doesn’t support suffixing with ‘i’ or ‘j’.

So we can conclude:

  • ISO C Standard doesn't support i, I, j, or J suffixes. These suffixes are a GCC extension.

  • i, j, I, and J are equivalent.

  • Attaching any of the aforementioned suffixes to an integer or floating-point constant makes it an imaginary-number constant.

This GNU extension is also supported by Clang.

Compiling with -pedantic-errors fails:

$ gcc c.c -pedantic-errors -o c
c.c: In function 'main':
c.c:5:17: error: imaginary constants are a GCC extension
    5 |         int i = 1i;
      |                 ^~

$ clang c.c -pedantic-errors -o c
c.c:5:17: error: imaginary constants are a GNU extension [-Werror,-Wgnu-imaginary-constant]
        int i = 1i;
                ^
1 error generated.

See also: What compiler options are recommended for beginners learning C?.

As of why i became 0:

From section 6.3.1.7 of the ISO C Standard regarding Real and Complex conversions:

When a value of real type is converted to a complex type, the real part of the complex result value is determined by the rules of conversion to the corresponding real type and the imaginary part of the complex result value is a positive zero or an unsigned zero.

When a value of complex type is converted to a real type, the imaginary part of the complex value is discarded and the value of the real part is converted according to the conversion rules for the corresponding real type.

So when you assign 1i to an int, it becomes 0 because the that's the real part of 1i, and the imaginary part is discarded.

ISO C does support I for the imaginary part (although it is not a suffix, and is a constant and requires multiplication; like 3 + 4*I), although support for complex.h and complex numbers is optional for the compiler. The compiler may define __STDC_NO_COMPLEX__ if it does not support such.

From the ISO C Standard, 7.3.1 Introduction:

....

The macro I expands to either _Imaginary_I or _Complex_I. If _Imaginary_I is not defined, I shall expand to _Complex_I.

¶7 Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then redefine the macros complex, imaginary, and I.

As of the suffixes a, b, et cetera, neither the ISO C Standard, nor the GNU C Standard has support for any such thing.

like image 63
Madagascar Avatar answered Sep 15 '25 10:09

Madagascar


The gcc compiler unfortunately comes in "safety hazard mode" by default, since it is by default using a non-standard superset of the C language called GNU C (-std=gnu17).

The GNU C language contains a lot of things that are in direct conflict with conforming C. It also contains lots of non-standard alternative features to things that already exist in standard, such as imaginary number support, flexible array members, alignment specifiers etc etc. In GNU mode, gcc is happy to let such things pass silently, even if they are non-conforming C or breaks a conforming C program.

In this case you happened to stumble upon the GNU extension for complex numbers where i is a non-standard imaginary part suffix. This is a different one than the complex number implementation introduced by the C99 standard.

If you care about C language conformance, you should always compile with -std=c17 -pedantic-errors.

like image 20
Lundin Avatar answered Sep 15 '25 10:09

Lundin