summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--md/writeup/c_macro_tricks.md128
1 files changed, 128 insertions, 0 deletions
diff --git a/md/writeup/c_macro_tricks.md b/md/writeup/c_macro_tricks.md
index 759cf70..4068272 100644
--- a/md/writeup/c_macro_tricks.md
+++ b/md/writeup/c_macro_tricks.md
@@ -250,5 +250,133 @@ void mul ( "there is 3");
void div ( "there is 1");
```
+## C11 generics
+### Match single argument
+Best part of it that it can match also typdefed structures. So now macroses
+can contain typechecking
+
+```
+#define type_str(T) _Generic( (T), int: "int",\
+long: "long",\
+A: "A",\
+default: "Unknown type")
+```
+
+#### Source
+```c
+typedef struct A
+{
+
+} A;
+
+#define type_str(T) _Generic( (T), int: "int",\
+long: "long",\
+A: "A",\
+default: "Unknown type")
+
+int main()
+{
+ A a;
+ printf("%s\n",type_str((long)1));
+ printf("%s\n",type_str((int)1));
+ printf("%s\n",type_str(a));
+}
+```
+
+#### Result
+
+```
+long
+int
+A
+```
+
+### Match multiple arguments
+
+```
+#define type_str(T1,T2) _Generic( (T1),\
+int: _Generic((T2),int:"int int", long: "int long", float: "int float", A: "int A", default: "int UNK"),\
+long: _Generic((T2),int:"long int", long: "long long", float: "long float", A: "long A", default: "long UNK"),\
+float: _Generic((T2),int:"float int", long: "float long", float: "float float", A: "float A", default: "float UNK"),\
+A: _Generic((T2),int:"A int", long: "A long", float: "A float", A: "A A", default: "A UNK"),\
+default: "UNK UNK" )
+```
+
+#### Source
+```
+typedef struct A
+{
+
+} A;
+
+#define type_str(T1,T2) _Generic( (T1),\
+int: _Generic((T2),int:"int int", long: "int long", float: "int float", A: "int A", default: "int UNK"),\
+long: _Generic((T2),int:"long int", long: "long long", float: "long float", A: "long A", default: "long UNK"),\
+float: _Generic((T2),int:"float int", long: "float long", float: "float float", A: "float A", default: "float UNK"),\
+A: _Generic((T2),int:"A int", long: "A long", float: "A float", A: "A A", default: "A UNK"),\
+default: "UNK UNK" )
+
+int main()
+{
+ A a;
+ printf("%s\n",type_str((long)1,1.f));
+ printf("%s\n",type_str((int)1,1));
+ printf("%s\n",type_str(a,a));
+}
+
+```
+
+#### Result
+
+```
+long float
+int int
+A A
+```
+### Generic printf
+```
+#define FF "%f "
+#define FS "%s "
+#define FD "%d "
+#define N ""
+#define PR2(S,T,T1,T2,...) printf(S,T,T1)
+#define PR1(S,T,T1,...) _Generic((T1),\
+ int: PR2(S FD,T,T1,__VA_ARGS__,N,N,N),\
+ float:PR2(S FF,T,T1,__VA_ARGS__,N,N,N),\
+ char*:PR2(S FS,T,T1,__VA_ARGS__,N,N,N),\
+ default:"")
+#define static_printf(T1,...) _Generic((T1),\
+ int: PR1(FD,T1,__VA_ARGS__,N,N,N),\
+ float:PR1(FF,T1,__VA_ARGS__,N,N,N),\
+ char*:PR1(FS,T1,__VA_ARGS__,N,N,N),\
+ default:"")
+```
+
+#### Source
+```
+int main()
+{
+ A a;
+ int b = 3, c = 4;
+ static_printf(1, 2.f);
+ printf("\n");
+ static_printf(b,c);
+ printf("\n");
+
+ static_printf("big float",0.01f);
+ printf("\n");
+}
+```
+
+#### Result
+
+```
+1 2.000000
+3 4
+big float 0.010000
+```
+
+## Links
+1. [https://baike.baidu.com/item/C11](https://baike.baidu.com/item/C11)