diff --git a/share/libc/stdint.h b/share/libc/stdint.h
index 839a90e3dc1132e9b5b6a947ef2c27164faf0ec4..f7a7d365b28c922b777312e625a406f4bee4e1b5 100644
--- a/share/libc/stdint.h
+++ b/share/libc/stdint.h
@@ -163,16 +163,6 @@ typedef __UINTMAX_T uintmax_t;
 #define WINT_MIN __FC_WINT_MIN
 #define WINT_MAX __FC_WINT_MAX
 
-/* ISO C: 7.18.4 */
-#define INT8_C(c) c
-#define UINT8_C(c) c
-#define INT16_C(c) c
-#define UINT16_C(c) c
-#define INT32_C(c) (c ## L)
-#define UINT32_C(c) (c ## UL)
-#define INT64_C(c) (c ## LL)
-#define UINT64_C(c) (c ## ULL)
-
 #define INTMAX_C(c) (c ## LL)
 #define UINTMAX_C(c) (c ## ULL)
 
diff --git a/src/kernel_internals/runtime/machdep.ml b/src/kernel_internals/runtime/machdep.ml
index 9ca2d913b5b020f1358e914adf3c6bd1990eae39..f7734b1c823b5d490e128c092bac634658099fbb 100644
--- a/src/kernel_internals/runtime/machdep.ml
+++ b/src/kernel_internals/runtime/machdep.ml
@@ -68,6 +68,47 @@ let pp_of_kind =
     "long long", "ll"
   ]
 
+let gen_precise_size_type fmt mach =
+  let open struct type ty = CHAR | SHORT | INT | LONG | LONGLONG end in
+  let all = [CHAR; SHORT; INT; LONG; LONGLONG] in
+  let size_of_ty t =
+    match t with
+    | CHAR -> 1
+    | SHORT -> mach.sizeof_short
+    | INT -> mach.sizeof_int
+    | LONG -> mach.sizeof_long
+    | LONGLONG -> mach.sizeof_longlong
+  in
+  let suffix_of_ty is_signed t =
+    let suff = try
+        List.assoc
+          (match t with
+           | CHAR -> "char"
+           | SHORT -> "short"
+           | INT -> "int"
+           | LONG -> "long"
+           | LONGLONG -> "long long") suff_of_kind
+      with Not_found -> Kernel.fatal "Undefined suffix type"
+    in
+    let suff = (if is_signed then "" else "U")^suff in
+    if suff = "" then "" else "## "^suff
+  in
+  let suffix is_signed n =
+    let t =
+      try
+        List.find (fun i -> size_of_ty i * 8 == n) all
+      with Not_found -> LONGLONG in
+    suffix_of_ty is_signed t
+  in
+  gen_define_string fmt "INT8_C(c)"   ("(c"^(suffix true   8)^")");
+  gen_define_string fmt "INT16_C(c)"  ("(c"^(suffix true  16)^")");
+  gen_define_string fmt "INT32_C(c)"  ("(c"^(suffix true  32)^")");
+  gen_define_string fmt "INT64_C(c)"  ("(c"^(suffix true  64)^")");
+  gen_define_string fmt "UINT8_C(c)"  ("(c"^(suffix false  8)^")");
+  gen_define_string fmt "UINT16_C(c)" ("(c"^(suffix false 16)^")");
+  gen_define_string fmt "UINT32_C(c)" ("(c"^(suffix false 32)^")");
+  gen_define_string fmt "UINT64_C(c)" ("(c"^(suffix false 64)^")")
+
 let max_val bitsize is_signed kind =
   let suff = List.assoc kind suff_of_kind in
   let suff = if is_signed then suff else "U" ^ suff in
@@ -249,6 +290,7 @@ let gen_all_defines fmt mach =
   gen_char_unsigned_flag fmt mach;
   gen_sizeof_std fmt mach;
   gen_char_bit fmt mach;
+  gen_precise_size_type fmt mach;
   gen_define_string fmt "__PTRDIFF_T" mach.ptrdiff_t;
   gen_define_string fmt "__SIZE_T" mach.size_t;
   gen_define_string fmt "__WCHAR_T" mach.wchar_t;
diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml
index e2fedba13a469501a094a3d0a87af7e7a9b8da98..ae7a41fd5008aace906238f7035fda8352b7dab1 100644
--- a/src/kernel_internals/typing/cabs2cil.ml
+++ b/src/kernel_internals/typing/cabs2cil.ml
@@ -6067,7 +6067,17 @@ and doExp local_env
       else
         abort_context "Unary ~ on a non-integral type"
 
-    | Cabs.UNARY(Cabs.PLUS, e) -> doExp (no_paren_local_env local_env) asconst e what
+    | Cabs.UNARY(Cabs.PLUS, e) ->
+      let (r, se, e, t as v) = doExp (no_paren_local_env local_env) asconst e what in
+      if isIntegralType t then
+        let newt = integralPromotion t in
+        let e' = makeCastT ~e ~oldt:t ~newt in
+        finishExp r se e' newt
+      else
+      if isArithmeticType t then
+        v
+      else
+        abort_context "Unary + on a non-arithmetic type"
 
     | Cabs.UNARY(Cabs.ADDROF, e) ->
       (* some normalization is needed here to remove potential COMMA, QUESTION
diff --git a/tests/syntax/oracle/sizeof.0.res.oracle b/tests/syntax/oracle/sizeof.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..aa1ba789ca9fca267ec802decd82a0ed1c226e9d
--- /dev/null
+++ b/tests/syntax/oracle/sizeof.0.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing sizeof.c (with preprocessing)
+/* Generated by Frama-C */
+#include "stdint.h"
+char c = (char)1;
+char a = (char)'a';
+int8_t i8 = (int8_t)125;
+uint8_t u8 = (uint8_t)230U;
+int16_t i16 = (int16_t)864;
+uint16_t u16 = (uint16_t)45213U;
+int32_t i32 = 864531;
+uint32_t u32 = 45213U;
+int64_t i64 = 753L;
+uint64_t u64 = 6453UL;
+int v = 645201;
+float f = (float)1.;
+double d = 1.;
+
diff --git a/tests/syntax/oracle/sizeof.1.res.oracle b/tests/syntax/oracle/sizeof.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..05c8abe3fa6d930520097aa9c3b94a8f07000f3e
--- /dev/null
+++ b/tests/syntax/oracle/sizeof.1.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing sizeof.c (with preprocessing)
+/* Generated by Frama-C */
+#include "stdint.h"
+char c = (char)1;
+char a = (char)'a';
+int8_t i8 = (int8_t)125;
+uint8_t u8 = (uint8_t)230U;
+int16_t i16 = (int16_t)864;
+uint16_t u16 = (uint16_t)45213U;
+int32_t i32 = 864531;
+uint32_t u32 = 45213U;
+int64_t i64 = 753LL;
+uint64_t u64 = 6453ULL;
+int v = 645201;
+float f = (float)1.;
+double d = 1.;
+
diff --git a/tests/syntax/sizeof.c b/tests/syntax/sizeof.c
new file mode 100644
index 0000000000000000000000000000000000000000..a27bf94011e4a4341faf3a7e948d360ce70ec2d4
--- /dev/null
+++ b/tests/syntax/sizeof.c
@@ -0,0 +1,42 @@
+/* run.config
+   EXIT: 0
+   STDOPT: -machdep x86_64
+   STDOPT: -machdep x86_32
+*/
+char c = 1;
+_Static_assert(sizeof(-c) == sizeof(int), "Integer promotion with minus");
+_Static_assert(sizeof(+c) == sizeof(int), "Integer promotion with plus");
+_Static_assert(sizeof (c) == sizeof(char), "sizeof numeric char");
+char a = 'a';
+_Static_assert(sizeof(a) == sizeof(char), "sizeof char");
+_Static_assert(sizeof ('a') == sizeof(int), "sizeof literal char");
+
+#include "stdint.h"
+
+int8_t i8 = INT8_C(125);
+uint8_t u8 = UINT8_C(230);
+_Static_assert(sizeof +i8 == sizeof +INT8_C(50), "i8");
+_Static_assert(sizeof +u8 == sizeof +UINT8_C(140), "u8");
+
+int16_t i16 = INT16_C(864);
+uint16_t u16 = UINT16_C(45213);
+_Static_assert(sizeof +i16 == sizeof +INT16_C(645231), "i16");
+_Static_assert(sizeof +u16 == sizeof +UINT16_C(8475), "u16");
+
+int32_t i32 = INT32_C(864531);
+uint32_t u32 = UINT32_C(45213);
+_Static_assert(sizeof +i32 == sizeof +INT32_C(645231), "i32");
+_Static_assert(sizeof +u32 == sizeof +UINT32_C(8475), "u32");
+
+int64_t i64 = INT64_C(753);
+uint64_t u64 = UINT64_C(6453);
+_Static_assert(sizeof +i64 == sizeof +INT64_C(6531), "i64");
+_Static_assert(sizeof +u64 == sizeof +UINT64_C(64751), "u64");
+
+int v = 645201;
+_Static_assert(sizeof +v == sizeof(int), "Integer is promote to integer");
+
+float f = 1.;
+_Static_assert(sizeof +f == sizeof(float), "Float promotion");
+double d = 1.;
+_Static_assert(sizeof +d == sizeof(double), "Double promotion");