let rec print_c_type t =
    let print = function
        Tvoid -> "void"
      | Tbuiltin t -> print_builtin_type t
      | Tpointer t ->
          if atomic_c_type t then "*"^(print_c_type t) else "*("^(print_c_type t)^")"
      | Tfunction( parameter_type_list, is_vararg, return_type ) ->
          let rec print = function
              [] -> ""
            | [t] -> print_c_type t
            | t::l -> (print_c_type t)^" * "^(print l)
          in
          "("^(print parameter_type_list)
          ^(if is_vararg then ", ..." else "")
          ^" -> "^(print_c_type return_type)^")"
      | Tarray( t, n ) ->
          (if atomic_c_type t then print_c_type t else "("^(print_c_type t)^")")
          ^"["^(match n with None -> "" | Some n -> string_of_big_int n)^"]"
      | Tstruct n -> "struct<"^(string_of_int n)^">"
    in
    match t.ct_const_p, t.ct_volatile_p with
        truetrue -> "const volatile "^(print t.ct_ty)
      |        truefalse -> "const "^(print t.ct_ty)
      |        falsetrue -> "volatile "^(print t.ct_ty)
      |        falsefalse -> print t.ct_ty