Thursday, November 19, 2009

C99 Features

Here is a simple example demonstrating some of the C99 features. It is a test program I wrote for learning from C99 standard. Although it doesn't cover all the new features for C99, I think it is at least a start for people who are not familiar to C99 like me.

Click HERE to download c99.c.



  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <complex.h>
  4 
  5 #define ppp printf("\n%s, line %d\n", __func__, __LINE__)
  6 
line 3: include the header for complex definations and declarations

  7 void data_type(void)
  8 {
  9     _Bool b = 2;
 10     long long int l;
 11     _Complex c = 1 + 2.3 * I;
 12     ppp;
 13 
 14     printf("  b = %d, sizeof b = %d\n", b, sizeof(b));
 15     printf("  sizeof l = %d\n", sizeof(l));
 16     printf("  c = %f + %f i, sizeof c = %d\n", creal(c), cimag(c), sizeof(c));
 17 }
 18 
line 9: boolean type
line 10: long long type
line 11: comlex type
line 15: the value of a boolean variable can only be 0 or 1
line 16: print the real number and imaginary number of the complex number

 19 void variable_length_array(int n)
 20 {
 21     int arr[n];
 22     ppp;
 23 
 24     printf("  arr: ");
 25     for (int i = 0; i < n; i++) {
 26         arr[i] = i;
 27         printf("%d ", arr[i]);
 28     }
 29     printf("\n");
 30 
 31     int arr2[n][n];
 32     printf("  size of arr2 = %d\n", sizeof(arr2)/sizeof(int));
 33 }
 34 
line 21: the lenght of the array is determined at run time
line 24: c++ style for loop initialization
line 31: two dimention array is fine, too

 35 #define dprint(...) printf(__VA_ARGS__)
 36 void variadic_macro(void)
 37 {
 38     ppp;
 39     dprint("  hello!\n");
 40     dprint("  %d + %d = %d\n", 2, 1, 3);
 41 }
 42 
line 35: __VA_ARGS__ will be replaced by the passed arguments during macro expansion
line 39, 40: variable arguemnts are used for the macro

 43 struct abc { int a; int b; int c[10]; };
 44 int foo(void) { /* do something... */ return 0; }
 45 


 46 void designated_initializer(void)
 47 {
 48     ppp;
 49 
 50     struct abc s1 = { .b = 1, .a = -1 };
 51     struct abc s2 = { .c[2] = 2 };
 52     printf("  s1.a = %d, s1.b = %d, s2.c[2] = %d\n", s1.a, s1.b, s2.c[2]);
 53 
 54     int arr[10] = { [2] = 22, [5] = 55 };
 55     struct abc s3[] = { [3].c[2] = 33 };
 56     printf("  arr[5] = %d, s3[3].c[2] = %d\n", arr[5], s3[3].c[2]);
 57 
 58     struct abc s4 = { .b = 4, .b = 5, .b = 6 };
 59     printf("  s4.b = %d\n", s4.b);
 60 
 61     struct xx { int x; struct abc sub; };
 62     struct xx s5 = { .sub.b = 5 };
 63     struct xx s6 = { .sub = s1 };
 64     printf("  s5.sub.b = %d, s6.sub.b = %d\n", s5.sub.b, s6.sub.b);
 65 }
 66 
line 50: members can be named in initializer lists
line 51: initialize only the 3rd object for the array member c
line 54, 55: initialize some array objects only
line 58: initialize several times, and the last one wins
line 62: initialize member b of the sub structure
line 63: initialize only the sub structure

 67 void cl(struct abc s)
 68 {
 69     printf("  s.a = %d, s.b = %d\n", s.a, s.b);
 70 }
 71 void compound_literal(void)
 72 {
 73     int *p = (int []){1, 2, 3};
 74     ppp;
 75 
 76     printf("  *p = %d, *(p+1) = %d\n", *p, *(p+1));
 77     cl((struct abc){ .a=9, .b=8 });
 78 }
 79 
line 73: composed with a construct with a brace'd initializer to create unnamed array's.
line 77: pass a compound literal argument to function cl (both compound literal and designated initializer are used)

 80 void flexible_array_member(void)
 81 {
 82     struct xx { int a; int arr[]; };
 83     struct xx *p;
 84     ppp;
 85 
 86     p = malloc(10 * sizeof(int));
 87     p->arr[8] = 8;
 88     printf("  p->arr[8] = %d\n", p->arr[8]);
 89     free(p);
 90 
 91     p = malloc(20 * sizeof(int));
 92     p->arr[18] = 18;
 93     printf("  p->arr[18] = %d\n", p->arr[18]);
 94     free(p);
 95 }
 96 
line 82: incomplete array without bounds of struct members is allowed (it must be the last member)
line 86: set p to a struct xx with array of length 9
line 91: set p to another struct xx with array of length 19

 97 int main(void)
 98 {
 99     data_type();
100     variable_length_array(5);
101     variadic_macro();
102     designated_initializer();
103     compound_literal();
104     flexible_array_member();
105 
106     //return 0;
107 }
line 106: compiler will add a 'return 0;' implicitly


The result of this program:
$ gcc -Wall -std=c99 c99.c
$ ./a.out

data_type, line 12
b = 1, sizeof b = 1
sizeof l = 8
c = 1.000000 + 2.300000 i, sizeof c = 16

variable_length_array, line 22
arr: 0 1 2 3 4
size of arr2 = 25

variadic_macro, line 38
hello!
2 + 1 = 3

designated_initializer, line 48
s1.a = -1, s1.b = 1, s2.c[2] = 2
arr[5] = 55, s3[3].c[2] = 33
s4.b = 6
s5.sub.b = 5, s6.sub.b = 1

compound_literal, line 74
*p = 1, *(p+1) = 2
s.a = 9, s.b = 8
flexible_array_member, line 84
p->arr[8] = 8
p->arr[18] = 18


Click HERE to download c99.c.


References:

2 comments:

xojoc said...

Thanks for the example, really useful.
BTW, on the lines 85-86 there is a bug. Malloc allocates space for 10 ints 1 for `a' and 9 for `arr'. With p->arr[9] you are accessing the 10th element. The same is true for lines 90-91.

Winfred said...

Aaah.. How stupid i am. Fixed. Thank you.