How to Write Function-Like Preprocessor Macros (C example)

Поділитися
Вставка
  • Опубліковано 4 жов 2024

КОМЕНТАРІ • 123

  • @JacobSorber
    @JacobSorber  3 роки тому +79

    In case, anyone else is wondering. You can generate preprocessed C code using the "-E" option in gcc and clang.

    • @AyushSharma-ny8bm
      @AyushSharma-ny8bm 3 роки тому +2

      Hi Jacob, I humbly insist you to make a GTK (GUI framework) setup and getting started video. Especially for "How to work with GTK and Makefile?"
      PS: I have a project to make using GTK, need help! I'm not even able to set it up and build the project using Makefile.

    • @AyushSharma-ny8bm
      @AyushSharma-ny8bm 2 роки тому

      @Rishab Tirupathi Thank you brother!🤗

  • @Neffins
    @Neffins 3 роки тому +21

    I feel like the answer to "let me know if you want to know more about X" is always yes Jacob, thank you.

  • @XenoTravis
    @XenoTravis 3 роки тому +19

    This deserved a bit more on the different features the preprocessor has to be considered a deep dive. I would be interested in more on this topic before making a compound video.

  • @nomadic-insomniac
    @nomadic-insomniac 3 роки тому +20

    Part 2 , variadic macros, stringizing ?
    My favourite example being
    #define LOG(fmt, ...) printf(fmt"
    ", ##__VA_ARGS__);
    Was mighty proud of myself when I figured how to use them :)
    One of my mentors once told me never to put functions into macros, you may get away with it once or twice but you will eventually fail, use inline functions instead.

    • @nallid7357
      @nallid7357 3 роки тому +2

      Your mentor also forgot to mention that modern compilers are smart enough to inline functions themselves rather than using the hint keyword 'inline'. Unless you're using old compilers, the mention of inlining functions is redundant (sometimes detrimental) to the compiler. Only in special cases do you ever use the keyword inline.

    • @saulaxel
      @saulaxel 2 роки тому +1

      @@nallid7357 You rarely talk about inlining without mentioning the inline keyword. I think that mentioning it, albeit mostly useless, is a good excluse to talk about these kinds of optimizations.

  • @alihanouch8028
    @alihanouch8028 10 місяців тому

    The best coding professor ever you got the best pedagogy so far.

  • @FintasticMan
    @FintasticMan 2 роки тому +13

    Do be aware that the typeof used in the last section is actually a GNU extension, and not officially part of the C specification. There is a possibility however that it might make it's way into C23 though.

    • @Vlad-1986
      @Vlad-1986 Рік тому +2

      That's cool! Sadly, most of my C programming is done under DOS with C89, so not going to see much usage of it. That can explain why I never heard of it

  • @deepakr8261
    @deepakr8261 3 роки тому +23

    Another interesting thing I learned from multiline macros is the advantage of using do/while(0) block for multiline macros over scoped usage(the compound multiline macro demonstrated by Jacob). Consider the below eg:
    #define CALL_FUNC do { /
    Do some stuff; /
    Call func() ;/
    }while (0)
    Usage in code:
    if (condition x)
    CALL_FUNC;
    else
    printf("Condition failed!");
    If CALL_FUNC was a scoped block (ie without do/while(0)), the semi-colon at the end of macro usage CALL_FUNC would terminate the if block causing compilation error due to the now zombied 'else' block. The do/while(0) safely circumvents this and thus has been a more preferred way to do multiline macros for me as it can now be used everywhere.

    • @saulaxel
      @saulaxel 2 роки тому +6

      Not exactly in this case. Take a look at the parenthesis around {}. When there is a ({ something }), it is, something surrounded by both parenthesis and brackets, it is a statement expressions, which is a gcc non-standard extension that behaves like a normal expression instead of behaving like a block statement; hence, it worls well with your example. This arguably has the benefits of using do{}while(0) but with a cleaner (maybe?) syntax.
      In this case, the drawback is that this is not portable, not that it fails in your example

    • @maxaafbackname5562
      @maxaafbackname5562 Рік тому

      A do while is an statement, not an expression.
      Therefor it can not used in the example of the video.
      That code "returns" a value from the macro, and must be an expression.
      A do while does not have/return a value.

  • @_veikkomies
    @_veikkomies 3 роки тому +2

    Definitely make a compound expression video!

  • @sallavatsal
    @sallavatsal 2 роки тому +2

    This is a very good way of explaining Macros! In fact, I've not seen anyone explain it in a language simpler than this. Because of this video, I will now be using typeof operator which I never understood before. Thanks Jacob!

  • @shaharslan3372
    @shaharslan3372 2 роки тому +1

    Now this what I call great teaching!

  • @xbz24
    @xbz24 Рік тому

    how does this only has 28k views rn damn, the multi line pre processor macro was insane

  • @sghsghdk
    @sghsghdk 3 роки тому +3

    Remeber to do it like this "do{ statements; } while(0)". That way ending semicolons are enforces and syntactically use of the macros works exactly like normal functions.

  • @Byynx
    @Byynx Рік тому

    Best macro video so far. It would be great to make another macro video but this time debunking some of those crazy macros that we see for instance in opengl/glew header files. Nothing like a real case scenario.

  • @shrutichavan2398
    @shrutichavan2398 2 роки тому +1

    Thank you so much for this detailed explanation, that's exactly what I was looking for today!

    • @JacobSorber
      @JacobSorber  2 роки тому

      You're welcome. Glad it was helpful.

  • @anon_y_mousse
    @anon_y_mousse 2 роки тому +1

    Even though it's `gcc` specific, this is a pretty good start for teaching about the preprocessor. I personally wish they'd just include a lot of C++'s more basic features in C, such as templates and function overloading and especially operator overloading. For a few years I did some development on Windows and I used Lcc-Win32. The guy that wrote it, started with just porting `lcc` to Windows, but he added a lot of awesome features while he was at it, such as operator overloading. He implemented a fairly complete IDE with a resource editor. If you ever do any Windows development, might be worth a shot.

  • @kaifahmedkhan4706
    @kaifahmedkhan4706 Рік тому

    Great explanation and examples!

  • @zakagg4707
    @zakagg4707 3 роки тому

    Many thanks, realy one of my best Chanel and yes we definitely want to see more about macros.

  • @ekinigdr2030
    @ekinigdr2030 3 роки тому +3

    great video again. I wish you mentioned some handy stuff like paste, stringinize, function name macro helper thingies. Also appearently there is this macro switch statement (maybe its a gcc addon) that works on types so you could write stuff like generic math libraries. Didnt know about compound statements that was kinda cool

    • @XenoTravis
      @XenoTravis 3 роки тому +3

      Good point. This video does deserve a bit more on the different features if it is considered a deep dive.

  • @berk473
    @berk473 2 роки тому

    I love your videos!! Please keep making them👍🏽

  • @shuaiqingluo3544
    @shuaiqingluo3544 3 роки тому +3

    Thanks for the great video! One quick question: why using the compound statement with declaring local variables solved the problem?

  • @abhishekupadhyay2641
    @abhishekupadhyay2641 3 роки тому +2

    I used to follow every video that you have posted. And simply I love it.
    Can you please start videos on kernels device drivers series?

  • @szeryk324
    @szeryk324 3 роки тому +2

    Very good video! I've just discovered your channel, you are doing great job man! I've just switched from being high level C++ developer to more low level C / embedded engineering and I find your videos extremely helpful. Thanks 😊

  • @AyushSharma-ny8bm
    @AyushSharma-ny8bm 3 роки тому +2

    Love the video!♥❣🔥
    Thank you, Jacob!
    Learned a completely new thing today!

    • @JacobSorber
      @JacobSorber  3 роки тому +1

      You're very welcome. Glad I could help.

    • @AyushSharma-ny8bm
      @AyushSharma-ny8bm 3 роки тому +2

      @@JacobSorber Hi Jacob, I humbly insist you to make a GTK (GUI framework) setup and getting started video. Especially for "How to work with GTK and Makefile?"
      PS: I have a project to make using GTK, need help! I'm not even able to set it up and build the project using Makefile.

  • @jankeshchakravarthy9389
    @jankeshchakravarthy9389 Рік тому

    @jacob Sorber - Very nice video and very clear. I have some follow on question. 1. Typeof operator. Is it part of standard C? 2. Is it possible to have a video with more issues with macro? Maybe, you can call that video as "pitfalls of macros in C". Please let me know, if you need any help in preparing the content. thanks again.

  • @diegonayalazo
    @diegonayalazo 2 роки тому

    Thanks

  • @user-ux2kk5vp7m
    @user-ux2kk5vp7m 3 роки тому +1

    I never knew that typeof() existed, that’s really cool

    • @user-ux2kk5vp7m
      @user-ux2kk5vp7m 3 роки тому

      @@Ricardo-C yeah I found that through some research. Same goes for the compound statement

    • @r3jjs
      @r3jjs Рік тому

      Pretty sure typeof() is a GNU extension, unless it was picked up by the main standard very recently.

    • @user-ux2kk5vp7m
      @user-ux2kk5vp7m Рік тому

      @@r3jjs its an extension added in C23

  • @Thel-foo
    @Thel-foo 10 місяців тому

    Damn. Thank you! This reminds me of generics.

  • @NunoFidalgo
    @NunoFidalgo 3 роки тому

    Your vids are great, kudos

  • @jimboy4090
    @jimboy4090 3 роки тому +5

    One thing to note also is that we cannot do recursion with macros

  • @boogy4you
    @boogy4you Рік тому

    When to use macros for code generation. is there a rule of thumb? Does it actually improve the code?

  • @pandasoli6581
    @pandasoli6581 Рік тому

    Could please explain the kinda of macros Check (framework for unit tests in C) uses? I believe they are a bit different

  • @aabdev
    @aabdev 2 роки тому +1

    How to calculate some crc function in compile time? It can be handy in order to put some structure in flash( text segment) when address is not determinated ?

  • @b4ttlemast0r
    @b4ttlemast0r 2 роки тому +1

    couldn't you do the same thing with a template function in C++?
    template T min(T a, T b) {
    return a < b ? a : b;
    }

    • @md2perpe
      @md2perpe 2 роки тому +1

      Yes, but that's C++ not C.

  • @rohithbhandari7836
    @rohithbhandari7836 3 місяці тому

    What is the difference between inline functions and macro like function?

  • @mandar.vaidya
    @mandar.vaidya Рік тому

    can you please create one using ##

  • @sanjayteja447
    @sanjayteja447 Рік тому

    how to avoid the problem of unguarded macros when multiple #includes are used?

  • @chikwendumcdonald1581
    @chikwendumcdonald1581 Рік тому

    How do you prevent double inclusion for a function macro???

  • @xCwieCHRISx
    @xCwieCHRISx 2 роки тому

    in c++ you could use macros as template functions when the operators are overloaded for the objects u pass in. Im not sure its good practice though.

  • @homeofjavascript
    @homeofjavascript 3 роки тому

    More about compound expression

  • @redcrafterlppa303
    @redcrafterlppa303 2 роки тому +1

    Couldn't you replace all constexpr functions with preprocessor functions since they all should be working at compile time?
    PS: Only asking if you could not if you should.

  • @LogicEu
    @LogicEu 3 роки тому

    Great topic! Another thing to consider when using macros is the expression evaluation and the use of parenthesis!!! For example, if you say MIN(x + 5, y + 5), it would evaluate to (x + 5 < y + 5), which is wrong. This can be solved by defining macros with extra parenthesis ((A) < (B) : (A) ? (B))

  • @harikrishnanb7273
    @harikrishnanb7273 3 роки тому +2

    Rust vs C ? what are the differences? Why rust is most loved? Is it really better than C or not ?

    • @nunyobiznez875
      @nunyobiznez875 3 роки тому +1

      Honestly, Rust is "most loved" because it's the shiny new toy, IMO. Better for what exactly? What's "better" is highly subjective, and varies from one situation to the next. Both languages give you the raw tools to accomplish whatever you want to do. It also really depends what you are trying to do or what you want to use it for. If you want to do systems programming on Linux or another Unix-like system, C is better. For embedded systems, C is better. If you are talking about for a Windows desktop App, then rust may be a better choice for your situation, as it has object oriented features. If you're a sloppy programmer or if you need features to help ensure an app is secure, then rust may be better, since it also has features that will protect you from yourself, which helps to enforce security and type safety. Although, it's certainly possible to write robust and secure C code as well, and many do, there's just no one looking over your shoulder to enforce it. C gives a lot more freedom, it makes the assumption the programmer knows what they're doing, and tries to stay out of their way. I appreciate the freedom C provides, but that also means you have more freedom to make mistakes as well. Though, that will also force you to learn more as well.
      If you're writing an app for the control rods at a nuclear power plant or the landing struts on an aircraft, perhaps C may not the best choice. Although both rust and C++ are sold as being systems programming languages, there has yet to be a kernel in either, and C is generally the language of choice for systems programming. Nearly every OS has primarily used C under the hood, even Windows. To be fair, rust hasn't been around that long though, but I doubt that would change anything. If you want to know which is better for learning though, I'd say C is much better to start with, because it's easier to learn and will help you learn how things work under the hood and why they work the way they do, and would probably make learning rust much easier afterward. C is a lightweight language, with fast compile time and performance. Although there are a LOT more C libraries, it doesn't have as many convenience features in the language itself, as many higher level languages do. That's great for learning, and great if you love programming, but not always the best if you just want to write something as quickly as possible. C's syntax is terse and elegant, though it's more of a do it yourself language. It's is a fairly easy language to learn and can be learned fully in just a couple of months, though it's more difficult than that to really master.
      Rust is a higher level language than C, it has more built-in safety and security features, and includes more tools that make "getting the job done" easier, like an online package manager, concurrency, security, safety and object oriented features, but all of that also adds overhead, increases the complexity of the language and the syntax, makes it a bit more restrictive, verbose, and tends to make it more difficult for beginners as well, since there's more to learn. If you believe more is always better though, then you might prefer rust. If you study the Unix Philosophy, or are accustomed to a Unix environment though, you'll appreciate the value of simplistic design, and you'll know that more is definitely not always better. I also personally dislike some of rust's syntax as well, so I haven't used it much myself. That may partially be a preference thing, but probably not completely, as I've heard similar criticism from others. But that's something you'd really probably need to judge for yourself. Hopefully I don't sound overly negative about rust, because that's not the intent. You asked if it is really "better" than C though, so I assume you've already heard the song of rust sung by it's promoters, about it being all sunshine, roses, and unicorn farts.
      The best advice I can give you though, is to read as much as you can about both from reliable, objective sources. Then learn both C and rust for yourself, in whichever order you choose, and decide for yourself which one you think is better, for whatever purpose you wish to use them for. In my experience, that's the only way you will ever really know which one is better for you, for any given task. Otherwise, you'll just keep getting different opinions, that won't really give you a feel for either language, from different people, who have very different needs, goals, and preferences than your own.

  • @simonmarabi2661
    @simonmarabi2661 2 роки тому

    does anyone knows which kind of extension is he using to have that typography?

  • @mrjoepietube
    @mrjoepietube 8 місяців тому

    preprocessor has strange behavior with inline asm. #define testfunc(x) asm("mov r0, # x") do'snot work because when used the x is not evaluated and replaced bij the numerber of calling code like testfunc(2);

  • @Alex492r
    @Alex492r 2 роки тому

    am i wrong , or these doesnt work on visual studio ( MS complier ) ??

  • @cmdlp4178
    @cmdlp4178 3 роки тому +2

    Unfortunately compound expressions and typeof are not in the c standard.

    • @JacobSorber
      @JacobSorber  3 роки тому +2

      Really?! I've never checked, but that's really sad. They're both really useful.

    • @cmdlp4178
      @cmdlp4178 3 роки тому

      @@JacobSorber Both are very useful GNU Extensions that are widely supported. But good news: I have researched a little and found oth that since very recently the typeof operator might get into C23. The standart commitee should be made aware of all other extensions. Many of them have shown their potential in linux (eg. include/linux/math.h), here typeof, statement expressions and useful builtins are used. But there were the min and max operators in gcc, MIN(a, b) == a

    • @fucku2b
      @fucku2b 3 роки тому

      you can kinda use C11's _GENERIC tho
      Edit: or in some cases you could use auto keyword/type

    • @kyrylmelekhin2667
      @kyrylmelekhin2667 3 роки тому +1

      Or you can just make another macro parameter that will specify the type you want. Preprocessor will paste it in.

  • @R4ngeR4pidz
    @R4ngeR4pidz 3 роки тому +1

    Any chance you could leave us with the command to output the pre-processed file? sounds like that's pretty crucial to debugging macros

  • @suncrafterspielt9479
    @suncrafterspielt9479 3 роки тому +2

    I did not get how with the compound expression the printf knows what to print... I mean, how does it know to print the result of the ternary operator and not from the variable declaration?
    ...Is my question even understandable? :o

    • @homelikebrick42
      @homelikebrick42 3 роки тому

      Printf gets the passed as an argument the result of the ternery operator

    • @suncrafterspielt9479
      @suncrafterspielt9479 3 роки тому

      As far as I understand it "n3 = MIN(n1 = getnum(), n2 = getnum());" will be replaced by
      "n3 = ({
      int _a = (n1 = getnum());
      int _b = (n2 = getnum());
      _a < _b ? _a : _b;
      });"
      but where is the assignment to n3? What would happen if I write
      "n3 = {
      1

  • @marusdod3685
    @marusdod3685 3 роки тому +4

    macros can also kinda mimic generics, except you have to declare for every type combination ahead of time

    • @robertkiestov3734
      @robertkiestov3734 3 роки тому +1

      >mask pfp
      Gross.

    • @marusdod3685
      @marusdod3685 3 роки тому +1

      @@robertkiestov3734 I never wear a mask irl

    • @terrorist_nousagi8747
      @terrorist_nousagi8747 3 роки тому

      @@robertkiestov3734 lol, what's gross about protecting yourself from germs?

    • @robertkiestov3734
      @robertkiestov3734 3 роки тому

      @@terrorist_nousagi8747 Masks are zionistic propaganda that don’t work or do anything.

    • @terrorist_nousagi8747
      @terrorist_nousagi8747 3 роки тому

      @@robertkiestov3734 Say that to Japan, wich is using masks way before the pandemic and has lower levels of contamination and slower growth of the pandemic

  • @gdotone1
    @gdotone1 Рік тому

    shouldn't a modern day compiler eliminate the need for ifndef... and only include a header once.

  • @virgoash7775
    @virgoash7775 3 роки тому +2

    I have a feeling that the 70's generation are the ones who know a lot about programming.

    • @JacobSorber
      @JacobSorber  3 роки тому +3

      I'm pretty sure that people who program a lot, and study programming a lot, are the ones who know a lot about programming. 😀

    • @virgoash7775
      @virgoash7775 3 роки тому

      @@JacobSorber I agree with you totally, but c programming language is an old language, it's shown in 1972, and programmers still use it until now because c is detailed and perfect in many ways, and it's shown at AT&T bell labs which is a company specializes in telecomunications, so servers are based at unix os which this last is programmed in C.
      I know you know this, but i mentioned 70's generation because they saw the beginning of computer's revolution, and what fetched me about you is you tell this younger generation including me, a generation that is so lazy want everything fast and easy like frameworks, instead of telling us to program with python like a lot do, you get straight to the point. and i watched your video about assembly language is a waste of time (p.s I liked this video a lot), you give me a word of wisdom the real programmer should really know how the computer works under the hood, and assembly is older than C, and as you say is a human readable machine code, which means this is the language that is good for embedded systems, but because C's compiler is made with it, it means that C converts into assembly.
      I'm a beginner but i started programming by reading older books, I see that a lot of functions was removed from this newer compilers, and programming industry is about details, so the learning curve it's not as the same from one generation to other, if you miss the ; in your c source code the computer won't compile the code, this is works for the humans brain as well, if any human didn't understand know that there is something undefined.
      And thank you. For the information that you give us is really helpful.

  • @Awwe12675
    @Awwe12675 3 роки тому

    Bro can you help me I need understand two problems thread and fork
    I mean I need implementation own!
    Sorry for my bad English please help

  • @1deepakbharti
    @1deepakbharti Рік тому

    I am using macro to access two functions according to case in header file and its cpp. If macro is defined 1st function will be active and if notdefined then 2nd function. But I am unable to achieve the same.

    • @1deepakbharti
      @1deepakbharti Рік тому

      Can you guide me regarding the same?

    • @JacobSorber
      @JacobSorber  Рік тому

      There's not enough info to know exactly what you're doing, but my guess is that you might be trying to make the preprocessor do more than it can. I would look at the preprocessed code (use the -E option) and it might make more sense what's going on.

  • @batuhanbatuhan6445
    @batuhanbatuhan6445 2 роки тому

    why is getnextnum not called four times?
    n3=((n1=gnn( )) < (n2=gnn( )) ? (n1=gnn( ) : (n2=gnn( ))
    should be printed 4 times shouldn't it?

    • @ammartirmizi
      @ammartirmizi 2 роки тому +3

      The ternary operator has one of the two outcomes after the "?". It depends on the initial expression. Thus, it is called thrice.

  • @gfsadds5574
    @gfsadds5574 3 роки тому

    Good video, is macro just like adding inline before function in C++?

  • @bamberghh1691
    @bamberghh1691 3 роки тому

    Isn't returning something from a block nonstandard?

    • @diceandbricks
      @diceandbricks 3 роки тому

      Yes. Statement expressions are gcc extensions.

  • @easyelectronics4364
    @easyelectronics4364 3 роки тому

    From where did you got so much of knowledge??? 😍

  • @aabdev
    @aabdev 3 роки тому

    How to write a function that gets the variable and prints its name (as in code) in run time (without preprocessor)?
    int val_a=4;
    int val_b=5;
    print_name(val_a);
    print_name(val_b);
    Console:
    >val_a
    >val_b

    • @gaelfortier2668
      @gaelfortier2668 2 роки тому +1

      You can't since variable names when compiled are lost. In machine binary, there is no variable name, only memory addresses and instructions

    • @gaelfortier2668
      @gaelfortier2668 2 роки тому

      What the preprocessor does is it keeps a copy of the variable's name in the executable so that you can print it later.
      #define GET_VAR_NAME(var) #var
      This generates in your code a string litteral with the name of the variable "var".

  • @ennio5763
    @ennio5763 Рік тому

    Compound statements are not part of the C standard, they are a compiler-specific extension.
    This is a problem for portability.

  • @MDarkus3
    @MDarkus3 3 роки тому

    Why in your example rand() always give same number (despite re-compiling 8:50) ? This looks a strange behavior to me for a random function generator oO

    • @auz7977
      @auz7977 3 роки тому +6

      this is because he didn't provide a unique seed to the random number generator by using srand().
      if the generator has the same seed, it will always produce the same sequence of "random" numbers.

  •  2 роки тому

    I prefer using C++ with templates and const's instead of using defines. But everyone has a different preference.

  • @BCOOOL100
    @BCOOOL100 Рік тому

    1:25 makefile

  • @李想-j6r
    @李想-j6r 3 роки тому

    This is cool, just talk more stuff about function-like marcos!

  • @ShadowlightSE
    @ShadowlightSE 3 роки тому

    Do macros always return a value? I never see a "return" in macros.

    • @rmaster934
      @rmaster934 3 роки тому +2

      They aren't technically a function, so no, they don't "return" anything. They just generate blocks of code that you specified.

    • @suncrafterspielt9479
      @suncrafterspielt9479 3 роки тому +6

      Macros are basically just copy pasting, just like defines and includes. Thats also why we had this strange behaviour described in the video 6:50

  • @arielspalter7425
    @arielspalter7425 3 роки тому

    The last example behaves like a template function.

  • @sledgex9
    @sledgex9 3 роки тому +3

    If in C++: Just use templates and gain type safety. Macros are hardly justified in modern C++ (at least most of the time).

  • @lef1970
    @lef1970 3 роки тому +2

    This seems like bad practice to me - if it behaves like a function, shouldn’t it be a function?

  • @Aleksandar0100
    @Aleksandar0100 3 роки тому +1

    >source code through patreon
    i thought the whole point of this channel is to help people learn C and computer science in general, putting the source behind a paywall contradicts that
    there are people who would still give you money regardless of you paywalling easy access to the code
    shame

    • @KarlKatten
      @KarlKatten 3 роки тому +5

      It literally does not contradict it, you don't need the source code to understand what he is teaching. How much teaching do you do for free?

    • @JacobSorber
      @JacobSorber  3 роки тому +4

      Thanks for the advice. You should think about creating your own channel. Then you can try out different approaches and run your channel in the way that makes the most sense to you.

    • @chaoticgoodcoding3700
      @chaoticgoodcoding3700 3 роки тому

      If typing out what you see during a free video is the greatest difficulty you face when learning C then you should pleased.

  • @fucku2b
    @fucku2b 3 роки тому +6

    I was expecting some cool weirdass macro uses like X macro pattern or variable length / optional arguments, also I think C11's _GENERIC macro func is rly interesting

    • @fucku2b
      @fucku2b 3 роки тому +1

      #/## operators