Ch supports the following new features added in C99.
- IEEE-754 floating-point arithmetic
- complex number
- variable length arrays (VLAs)
- type generic mathematical functions for polymorphism
- long long and unsigned long long
- mixing declarations and code
- binary integral constants
- predefined identifier __func__
- the variable argument list macro
- hexadecimal floating-point constants
- // comments
- the header file complex.h
- the header file fenv.h
- the header file inttypes.h
- the header file iso646.h
- the header file stdbool.h
- the header file stdin.h
- the header file tgmath.h
- the header file wchar.h
- the header file wctype.h
- new translation limits
- va_copy() in header file stdarg.h
- keywords restrict and inline
- remove implicit int
IEEE-754 floating-point arithmetic
#include <stdio.h>
#include <math.h>
int main() {
printf("1/0.0 = %f\n", 1/0.0);
printf("-1/0.0 = %f\n", -1/0.0);
printf("0.0/0.0 = %f\n", 0.0/0.0);
printf("sqrt(-1.0) = %f\n", sqrt(-1.0));
printf("INFINITY/INFINITY = %f\n", INFINITY/INFINITY);
}
The output is:
1/0.0 = inf
-1/0.0 = -inf
0.0/0.0 = nan
sqrt(-1.0) = nan
INFINITY/INFINITY = nan
complex number
/* complex in C99 is a built-in data type.
complex in C++ is a class. They are not compatible.
A program using complex conforming either C99 or C++ can readily run
in Ch without modification. */
#include <stdio.h>
#include <complex.h>
int main() {
double complex z1 = 1+I*2; // C99 and Ch
double_complex z2 = double_complex(1, 2); // C++ and Ch
double complex z3 = complex(1, 2); // Ch
double complex sz1, sz2, sz3;
sz1 = csqrt(z1); // C99 and Ch
sz2 = sqrt(z2); // C++ and Ch
sz3 = sqrt(z3); // C++ and Ch
printf("sz1 = %f, %f\n", creal(sz1), cimag(sz1)); // C99 and Ch
printf("sz2 = %f, %f\n", real(sz2), imag(sz2)); // C++ and Ch
printf("sz3 = %f\n", sz3); // Ch, added for users's convenience
}
The output is:
sz1 = 1.278020, 0.786151
sz2 = 1.278020, 0.786151
sz3 = complex(1.278020,0.786151)
variable length arrays (VLAs)
Example 1:
#include <stdio.h>
void func(int n, int m, int a[n][m]);
void func(int n, int m, int a[*][*]);
void func(int n, int m, int a[n][m]) { // a is VLA
int b[n][m], c[n]; /* b and c are VLAs */
printf("sizeof(b) = %d\n", sizeof(b));
printf("sizeof(c) = %d\n", sizeof(c));
printf("a[1][2] in func() = %d\n", a[1][2]);
a[1][2] = 100;
}
int main() {
int a1[2][3] = {1,2,3,
4,5,6};
int a2[3][4] = {1,2,3,4,
5,6,7,8,
9,10,11,12};
func(2, 3, a1);
printf("a1[1][2] in main() = %d\n", a1[1][2]);
func(3, 4, a2);
printf("a2[1][2] in main() = %d\n", a2[1][2]);
return 0;
}
The output is:
sizeof(b) = 24
sizeof(c) = 8
a[1][2] in func() = 6
a1[1][2] in main() = 100
sizeof(b) = 48
sizeof(c) = 12
a[1][2] in func() = 7
a2[1][2] in main() = 100
Example 2:
#include <stdio.h>
#include <chplot.h>
int main() {
int n;
scanf("%d", &n);
double x[n], y[n];
...
plotxy(x, y, n, "title", "x", "y");
return 0;
}
The variable n contains the number of elements
for the deferred-shale arrays x and y. The value for
the variable n is obtained from the user input.
type generic mathematical functions for polymorphism
#include <stdio.h>
#include <tgmath.h>
#include <complex.h>
int main() {
int i=3;
float fi, f=3;
double d=3;
complex z=3;
double complex dz=3;
fi = sin(i);
f = sin(f);
d = sin(d);
z = sin(z);
dz = sin(dz);
printf("fi = %f\n", fi);
printf("f = %f\n", f);
printf("d = %f\n", d);
printf("z = %f\n", z);
printf("dz = %f\n", dz);
}
The output is:
fi = 0.141120
f = 0.141120
d = 0.141120
z = complex(0.141120,-0.000000)
dz = complex(0.141120,-0.000000)
long long and unsigned long long
#include <stdio.h>
int main () {
unsigned long long u;
long long l;
u = 20ULL;
l = 20LL;
printf("u = %llu\n", u); // output: u = 20
printf("l = %lld\n", l); // output: l = 20
printf("sizeof(l) = %d\n", sizeof(l)); // output: l = 8
scanf("%lld", &l); // type input of "22"
printf("l = %lld\n", l); // output: l = 22
return 0;
}
mixing declarations and code
int main() {
int x, y;
x = 3;
y = 4;
int xy = x*y;
int a[xy];
}
binary integral constants
/* Binary I/O */
#include <stdio.h>
int main() {
unsigned int address;
unsigned char *p, mask = 0b00110101; // Binary integer
p = (char *)&address; /* p can point to a hardware memory address */
*p = mask;
printf("*p = %d\n", *p); // output decimal integer
printf("p = %b\n", mask); // output binary integer starting with 1
printf("p = %7b\n", *p); // output 7 bits of binary integer
printf("p = %8b\n", *p); // output 8 bits of binary integer
printf("p = %4b\n", *p); // output 4 bits of binary integer, but get 6
// because there are 6 non-zero bits
scanf("%b", p); // accept 011 as 3
}
/* output
*p = 53
p = 110101
p = 0110101
p = 00110101
p = 110101
*/
predefined identifier __func__
#include <stdio.h>
void funct() {
printf("Function %s() is called.\n", __func__);
}
int main () {
funct();
}
/* output
Function funct() is called.
*/
the variable argument list macro
#define debug(...) fprintf(stderr, __VA_ARGS__)
debug("Flag");
debug("x = %d\n", x);
#define showlist(...) puts(#__VA_ARGS__)
#define report(test, ...) ((test)?puts(#test):\
printf(__VA_ARGS__))
results in
fprintf(stderr, "Flag" );
fprintf(stderr, "x = %d\n", x );
puts( "The first, second, and third items." );
((x>y)?puts("x>y"):
printf("x is %d but y is %d", x, y));
hexadecimal floating-point constants
> 0X2P3
16.0000
> 0x1.1p0
1.0625
> 0x1.1p1F
2.12