From b8657880fb0ef8720d4edaae52bd5cf2a58ca275 Mon Sep 17 00:00:00 2001 From: FreeArtMan Date: Mon, 9 Oct 2017 01:25:56 +0100 Subject: Added notes about _Generic's --- md/writeup/c_macro_tricks.md | 128 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) (limited to 'md/writeup') 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) -- cgit v1.2.3