Stories
Slash Boxes
Comments

SoylentNews is people

posted by martyb on Saturday December 02 2017, @01:48PM   Printer-friendly
from the see-what-we-did-there? dept.

https://www.cossacklabs.com/blog/macros-in-crypto-c-code.html

Like death and taxes, one thing that you can be sure of is that using C macros in a modern software project will cause a debate. While for some macros remain a convenient and efficient way of achieving particular programming goals, for others they are opaque, introduce the unnecessary risk of coding errors, and reduce readability.

The criticism of macros is particularly acute in the wider security community. Among Cossack Labs' engineers and the core Themis crypto library contributors there are people who previously worked on auditing cryptographic implementations of critical code. Their typical knee-jerk reaction to macros was always "kill it with fire and never use it again". Taking no sides, we would like to assess both pros and cons of using such dangerous things as macros in security code (as we faced the issue when developing Themis) and suggest some techniques for lowering the accompanying risks.

We'll also discuss a custom "for-audit" build target for Themis designed specifically to generate source code that exposes the macros to inspection because we appreciate the need for security software to be subject to detailed source code scrutiny.


Original Submission

This discussion has been archived. No new comments can be posted.
Display Options Threshold/Breakthrough Mark All as Read Mark All as Unread
The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
(1)
  • (Score: 3, Insightful) by crafoo on Saturday December 02 2017, @02:13PM (11 children)

    by crafoo (6639) on Saturday December 02 2017, @02:13PM (#604269)

    I guess my opinion is that they should have just written out each error check test case and been done with it. It would have been more readable and not all that much more typing. Also, if you're going to use a macro for C error handling, maybe consider just using GOTO. Do the custom stuff you need and then jump to the standardized stuff you need instead of wrapping it up in a macro.

    My feeling is that once you've put a conditional or flow-control structure in a macro you've made a mistake.

    I don't have a lot of love for C++ templates either. I guess I've seen them used effectively, although there has always been a competing library that didn't use them and had at least as good performance ... so .. not convinced on the C++ template subject either.

    • (Score: 0) by Anonymous Coward on Saturday December 02 2017, @08:32PM (4 children)

      by Anonymous Coward on Saturday December 02 2017, @08:32PM (#604385)

      I have been putting a lot of thought into this. For standard C stuff we should be pushing to port constexpr and templates backwards into C from C++. #define is a poor mechanism to define code in. I have been feeling more explicit is better than implicit for awhile now. We are abusing the pre-processor to basically create code and then hide it. There have been a few times where I would have to unwind a define into a real function just to figure out where the subtle bug is. Because none of the existing debuggers let you trace them. This problem has been around a long time and we are abusing the compiler into fixing it. We should be creating structures (hehe) to make it easier for us to do these things instead of abusing current structures. Sure it is 'valid' but over the years #define has become a hell hole of code abuse. All because we have no real other way to do it. I have also seen people abuse #include. I want to hurt them when I see it. It is meaningless to do other than to somehow unpollute your global space.

      Most template slowness was because the compilers were just not really ready for it. They are now. They are doing a very good job at runtime inline and making methods. Whereas the original one just treated it as a super define and inlined everything yet treated it as an atomic unit with no optimization. Which lead to code bloat and poor cache coherency.

      My point is we are already doing basically what templates do, but abusing #define to do it. Why not make the pattern a first class citizen and make our lives easier? We are not going to magically stop doing it.

      • (Score: 2) by Pino P on Saturday December 02 2017, @11:36PM (3 children)

        by Pino P (4721) on Saturday December 02 2017, @11:36PM (#604462) Journal

        Once you backport templates to C, why not just use those features of C++? Is it to target platforms such as 6502-based retro computers that barely have a C89 compiler, let alone a compiler for modern C++?

        And even in C++, you still can't automatically pass __FILE__ and __LINE__ at the place of instantiation (as opposed to the place of definition) without either A. a macro or B. explicitly repeating __FILE__ and __LINE__ in every expression that might require them. Option B violates the Don't Repeat Yourself principle [wikipedia.org].

        • (Score: 2) by arcz on Sunday December 03 2017, @03:14PM (2 children)

          by arcz (4501) on Sunday December 03 2017, @03:14PM (#604675) Journal

          __FILE__ and __LINE__, are, imo, two of the only useful macros. My favorite macro is one I made called AT. I just do:

          std::cerr << AT << "Something happened." << std::endl;

          And that turns into "./bla.c:99:void foo::bar(int): Something happened."

          Good macros:

          • Do thing like this, using __FILE__ and __LINE__
          • Add code/remove code based on compiler or CPU architecture.

          Bad macros:

          • Do ANYTHING that could be done without them, including by switching from C to C++ and using templates.


          #ifdef __clang__
          #define CLANG_OPT_BARRIER std::atomic_signal_fence(std::memory_order_seq_cst)
          #else
          #define CLANG_OPT_BARRIER
          #endif

          The above code* would allow me to inject optimization barriers in clang but not other compilers. (clang's somewhat poor optimization passes on occassion make this needed due to optimizer "bugs" [well, techincally the code still works, but it might be 10x slower in some cases than without this trick])
          *Not actually tested, as I usually just add #ifdef __clang__ directly into my source. But IIRC this is basically what it would do.

          I also love macros for doing this:

          static inline size_t index1_pv(size_t n) __attribute__((always_inline))
              {
          #ifdef __x86_64__
                  if (rpnx_unlikely(n==0)) return 0;
                  else
                      {
                          size_t i;
                          asm("bsrq %1,%0\n" : "=r"(i) : "r"(n));
                          return i;
                      }
          #else
                  int i = 0; while ((1 << i)

          This one is a real example of my code (in my monoque repository). This is a great use of macros! I have a fast instruction for intel platforms and a generic one for others. So this code runs VERY fast on intel x86_64! (basically two instructions) vs the nested loop used on others.

          • (Score: 2) by Pino P on Sunday December 03 2017, @05:28PM (1 child)

            by Pino P (4721) on Sunday December 03 2017, @05:28PM (#604721) Journal

            Instead of using macros for the last case, you could use separate files:

            // index1_pv_amd64.c
            static inline size_t index1_pv(size_t n) __attribute__((always_inline))
                {
                    if (rpnx_unlikely(n==0)) return 0;
                    else
                        {
                            size_t i;
                            asm("bsrq %1,%0\n" : "=r"(i) : "r"(n));
                            return i;
                        }

            // index1_pv_pure.c
            static inline size_t index1_pv(size_t n) __attribute__((always_inline))
                {
                    int i = 0; while ((1 << i)

            Then the x86-64 target would compile and link the _amd64 source files, while other targets would use the pure C file.

            • (Score: 2) by arcz on Saturday December 09 2017, @05:03PM

              by arcz (4501) on Saturday December 09 2017, @05:03PM (#607716) Journal

              One of the few things I hate more than macros are complex build systems.
              Also that code needed to be inlinable so it had to go in a header. Platform specific headers would be a nightmare.

    • (Score: 3, Insightful) by fyngyrz on Saturday December 02 2017, @10:59PM (5 children)

      by fyngyrz (6567) on Saturday December 02 2017, @10:59PM (#604445) Journal

      C macros are fine. Poor programmers aren't.

      This, as with many other things, strikes me as blaming the language for the weakness of the practitioner. Which, in the case of operations that employ programmers, also means someone's been hiring people for the wrong reasons (like degrees / age / sex / court records / location / health / instead of skill, for example.)

      There's good code and poor code; and macros are code. If people are writing poor macros, then fix your people problem. Either train them more, or stop hiring incompetents.

      If your organization is not keeping track of the quality of code your employees / members are writing and getting blindsided by this sort of thing, why then you have another problem.

      And if it's you that's unable to deal with macros... time for some self-improvement. The macro code capabilities in c aren't broken. Guess what that leaves to fix?

      • (Score: 2) by Pino P on Saturday December 02 2017, @11:40PM (3 children)

        by Pino P (4721) on Saturday December 02 2017, @11:40PM (#604463) Journal

        stop hiring incompetents

        Easier said than done. Or would you please explain an efficient way to sort out dozens of applications by incompetent candidates to a particular position en masse?

        The macro code capabilities in c aren't broken.

        They're not type-safe. Some people include not type-safe in broken.

        • (Score: 3, Insightful) by fyngyrz on Saturday December 02 2017, @11:59PM (2 children)

          by fyngyrz (6567) on Saturday December 02 2017, @11:59PM (#604470) Journal

          would you please explain an efficient way to sort out dozens of applications by incompetent candidates to a particular position en masse?

          After you've determined that they say they're really good at the language you plan to have them use (demand/specify that info in the job app), then you test them. If you're hiring programmers without testing them, we've found (at least one of) your problems.

          Tests should be progressive; not stupid puzzles, or dips into realms that have to relevance to the job at hand, either. You can get newbies in and out of a test sequence in just minutes; they'll never survive the most simple questions about language details. Better programmers will take longer to check out. But competent testing is an absolute requirement to fill programming positions – if you don't want to be saddled with people who will do damage to the task(s) at hand.

          Also, don't ask for X years of experience in X. Ask for high competence in X. The former doesn't imply the latter, though one might (naively) think so.

          They're not type-safe. Some people include not type-safe in broken.

          Yes, well, you shouldn't hire people with that kind of skills deficit. Problem solved! Anything else I can help you with? :)

          c'mon, smile. Not kidding, though. A fundamental (not basic) programmer skill is managing types. If the language doesn't do it, it's your job (and if the language does do it, there's still no excuse for you to be bad at it.)

          • (Score: 0) by Anonymous Coward on Sunday December 03 2017, @01:09AM

            by Anonymous Coward on Sunday December 03 2017, @01:09AM (#604493)

            What you're suggesting sounds too hard. Wouldn't it be better to just keep turning away introverts, since they fail our shallow personality tests by not being social enough? Wouldn't it be easier to just throw out the applications of anyone who doesn't have a degree? Look how much time we're saving!

            Ugh, why is there a shortage of talented individuals!? We need foreigners to fill the gaps!

          • (Score: 2) by Pino P on Sunday December 03 2017, @03:29AM

            by Pino P (4721) on Sunday December 03 2017, @03:29AM (#604551) Journal

            You can get newbies in and out of a test sequence in just minutes; they'll never survive the most simple questions about language details. Better programmers will take longer to check out.

            It still costs quite a bit of money to administer the tests, especially when it involves flying in candidates from a thousand miles away. This competent testing had better provide improvement in quality that is measurable and substantial, or the shareholders won't stand for it.

            A fundamental (not basic) programmer skill is managing types. If the language doesn't do it, it's your job

            Then why not just write all programs in assembly language and make the programmer do everything?

      • (Score: 2) by DutchUncle on Sunday December 03 2017, @05:22AM

        by DutchUncle (5370) on Sunday December 03 2017, @05:22AM (#604578)

        Actually, C macros sort of suck, compared with IBM assembler macros from the 1970s, or Motorola's macro assembler for the 68000. IBM macros had capabilities close to templates in C++. That said, within the limits of what C macros can do, I agree with your premise that it's not the tool's fault if the programmer uses it badly.

  • (Score: 5, Insightful) by Virindi on Saturday December 02 2017, @02:15PM (2 children)

    by Virindi (3484) on Saturday December 02 2017, @02:15PM (#604271)

    Macros are just a tool. Like many language (and preprocessor) constructs, it is easy to use them poorly and difficult to use them well. C/CPP is full of such constructs.

    It's really up to the programmer to use any language in a way that makes "what is actually happening" clear to the reader. Hiding what is actually happening, rather than merely trying to make things easier to read but still clear in meaning, is the way of evil.

    • (Score: 2) by maxwell demon on Saturday December 02 2017, @06:14PM (1 child)

      by maxwell demon (1608) on Saturday December 02 2017, @06:14PM (#604337) Journal

      The problem with C macros is that they are a rather blunt tool. In most cases, the use of macros results in the code equivalent of driving a screw in with a hammer.

      Note that the problem is not with the concept of macros as such, it's with the specific way macros are implemented in C, namely using a preprocessor which knows very little about the structure of C programs.

      --
      The Tao of math: The numbers you can count are not the real numbers.
      • (Score: 2) by coolgopher on Sunday December 03 2017, @12:25AM

        by coolgopher (1157) on Sunday December 03 2017, @12:25AM (#604479)

        For all its bluntness, I miss the C-preprocessor whenever I'm in a language that doesn't support pre-processing (and doesn't lend itself to pre-processing via `make`). Commonly I also miss the relative type safety of C then.

        A point maybe worth mentioning is that it's typically possible to use whatever pre-processor you want, it doesn't have to be /usr/bin/cpp. The stuff done in TFA could be implemented in that manner for example.

        Gcc doesn't make it overly easy, though this post [stackoverflow.com] lists a way. I remember one compiler I used many moons ago had a simple -cpp switch with which you specify the pre-processor you wanted. It *might* have been the SunOS C compiler, but don't quote me on that please :)

  • (Score: 2, Insightful) by The Mighty Buzzard on Saturday December 02 2017, @02:16PM (9 children)

    by The Mighty Buzzard (18) Subscriber Badge <themightybuzzard@proton.me> on Saturday December 02 2017, @02:16PM (#604272) Homepage Journal

    Like death and taxes, one thing that you can be sure of is that using C macros in a modern software project will cause a debate. While for some macros remain a convenient and efficient way of achieving particular programming goals, for others they are opaque, introduce the unnecessary risk of coding errors, and reduce readability.

    Anyone using macros in production code should be killed to death unless they expand the macro in a comment above each use. It may save your monkey ass a few keystrokes but it costs every single person who ever has to touch your code at least an order of magnitude more time than it saved you.

    --
    My rights don't end where your fear begins.
    • (Score: 3, Insightful) by c0lo on Saturday December 02 2017, @02:35PM (5 children)

      by c0lo (156) Subscriber Badge on Saturday December 02 2017, @02:35PM (#604280) Journal

      unless they expand the macro in a comment above each use.

      You mean `(g)cc -E` ? Yeah, that's a hard one.

      --
      https://www.youtube.com/watch?v=aoFiw2jMy-0 https://soylentnews.org/~MichaelDavidCrawford
      • (Score: 2) by The Mighty Buzzard on Saturday December 02 2017, @02:53PM (4 children)

        by The Mighty Buzzard (18) Subscriber Badge <themightybuzzard@proton.me> on Saturday December 02 2017, @02:53PM (#604289) Homepage Journal

        Which means you have to have two copies of every file you're working on open and remember not to type in the one you can read? Yeah, that's a real winner of an option.

        No, man, there is no good argument for decreasing readability of production code to save one person some time. Not with 1337 perl that only you can read and not with C macros.

        --
        My rights don't end where your fear begins.
        • (Score: 5, Insightful) by tonyPick on Saturday December 02 2017, @03:37PM (3 children)

          by tonyPick (1237) on Saturday December 02 2017, @03:37PM (#604299) Homepage Journal

          Anyone using macros in production code should be killed to death unless they expand the macro in a comment above each use.

          Counter-examples: debug macros wrappering logging, handling vestigial compiler warnings while using -Wall/-Werror, crossplatform/multiplatform system code substitutions....

          No, man, there is no good argument for decreasing readability of production code to save one person some time.

          I'd argue overly verbose commenting, like "expand the macro in a comment" does more to reduce readability, and clean/hygenic/referentially transparent macro implementations can improve it.

          (On the other hand there's a special circle of hell reserved for people who write macro code that doesn't behave like that, and a lower one for people who make macros that don't *very* *obviously* look like Macros at first glance.)

          • (Score: 2) by Pino P on Saturday December 02 2017, @11:49PM

            by Pino P (4721) on Saturday December 02 2017, @11:49PM (#604465) Journal

            debug macros wrappering logging

            This sounds similar to aspect-oriented programming.

            crossplatform/multiplatform system code substitutions

            Let me predict the anti-macro hardliners' likely response, based on what I've picked up in discussions on this site and others like this about web applications:

            Anything that can vary from one platform to another ought to be in a separate file or separate set of files, one for each platform. That way, instead of #ifdef MACOS, you get macos.c. You end up with a driver for each platform that implements a common interface to the platform-independent parts of the program. For things like common data types used by the platform-independent parts, you can use typedef instead of macros.

            Or better yet, if there's a business case to make your client application available to users of multiple platforms, there's probably a business case to give the same client spec to separate programming teams, each specializing in a different client platform, so that each platform can get a client application that ideally plays to the strengths and user expectations of each platform. For example, the Mac and iOS versions can take advantage of Core Data."

          • (Score: 2) by coolgopher on Sunday December 03 2017, @12:28AM

            by coolgopher (1157) on Sunday December 03 2017, @12:28AM (#604480)

            Amen.

            Add to that another really common one, being rounds of cryptographic operations.

            Macros *increase* readability when used properly.

          • (Score: 2) by The Mighty Buzzard on Sunday December 03 2017, @02:24AM

            by The Mighty Buzzard (18) Subscriber Badge <themightybuzzard@proton.me> on Sunday December 03 2017, @02:24AM (#604524) Homepage Journal

            You're entitled to your opinion. I just hope I never have to come behind and fix any of your code.

            I'd argue overly verbose commenting, like "expand the macro in a comment" does more to reduce readability...

            Yeah, that would only be a problem if you can't read the code well. If you understand what you're looking at, seeing the actual code adds clarity instead of removes it. If you don't, you need to step back from the keyboard and hand the project off to someone who does.

            --
            My rights don't end where your fear begins.
    • (Score: 4, Touché) by bzipitidoo on Saturday December 02 2017, @05:27PM (2 children)

      by bzipitidoo (4388) on Saturday December 02 2017, @05:27PM (#604325) Journal

      What's your feeling about code generators? Code to generate code? How about templates? Do you hate them too, or only the way C macros goes about it?

      • (Score: 2) by Pino P on Saturday December 02 2017, @11:53PM

        by Pino P (4721) on Saturday December 02 2017, @11:53PM (#604467) Journal

        What's your feeling about code generators? Code to generate code?

        It depends on the difficulty of either formally proving the correctness of the code generators or auditing their output. The featured article is about making a code generator's output more auditable.

        How about templates?

        The key difference is that C++ templates are more type-safe than C preprocessor macros. But C preprocessor macros still have two advantages: availability on platforms with no C++ compiler (such as MOS 6502), and ability to use __FILE__ and __LINE__ at the place where a macro is used as opposed to where it is defined.

      • (Score: 2) by The Mighty Buzzard on Sunday December 03 2017, @02:12AM

        by The Mighty Buzzard (18) Subscriber Badge <themightybuzzard@proton.me> on Sunday December 03 2017, @02:12AM (#604521) Homepage Journal

        I have no love for any "I'm too lazy to type this out every time and too 1337 to just abstract it out with a wrapper function" code. Not in any language.

        --
        My rights don't end where your fear begins.
  • (Score: 4, Interesting) by acid andy on Saturday December 02 2017, @02:50PM (9 children)

    by acid andy (1683) on Saturday December 02 2017, @02:50PM (#604286) Homepage Journal

    I can sort of see the argument that they make security critical or safety critical code harder to properly audit in that they add a layer of obfuscation over the raw code but for much the same reason I strongly disagree with the criticism that they reduce readability. One of the key benefits of a macro is that, if used sensibly, it can reduce an ugly, unwieldy, hard to read expression, to a short, human readable form. For those that are religiously against macros, it would be easy enough to replace one with an inline function in many cases but you'd still have to code hop to the function definition to read it so I don't see that it would help the readability hugely.

    --
    If a cat has kittens, does a rat have rittens, a bat bittens and a mat mittens?
    • (Score: 3, Interesting) by tonyPick on Saturday December 02 2017, @04:03PM (1 child)

      by tonyPick (1237) on Saturday December 02 2017, @04:03PM (#604312) Homepage Journal

      it would be easy enough to replace one with an inline function in many cases but you'd still have to code hop to the function definition to read it so I don't see that it would help the readability hugely.

      Playing devils advocate (even though I agree with your general point), one issue is that functions are easier to reason about than macros in C, since function calls will always be pass by value, but macro implementations can change argument values in place in unexpected ways, or create shadow variables which lead to unexpected/incorrect results.

      Quick example would be mixing postfix operators with macros: something like" #define SQUARE(x) ((x)*(x))" Can be passed "SQUARE(x++)" which expands as "(x++) * (x++)" - x gets incremented twice, rather than once, and the result will probably not be what you expect. You can't make this mistake with a function call.

      • (Score: 4, Informative) by Pino P on Saturday December 02 2017, @11:57PM

        by Pino P (4721) on Saturday December 02 2017, @11:57PM (#604469) Journal

        Can be passed "SQUARE(x++)" which expands as "(x++) * (x++)" - x gets incremented twice, rather than once

        No, that's undefined behavior because the two uses of ++ are unsequenced [wikipedia.org]. A high-quality compiler ought to emit a diagnostic for easily detectable undefined behaviors such as this.

    • (Score: 2) by theluggage on Saturday December 02 2017, @04:10PM

      by theluggage (1797) on Saturday December 02 2017, @04:10PM (#604314)

      For those that are religiously against macros, it would be easy enough to replace one with an inline function in many cases but you'd still have to code hop to the function definition to read it so I don't see that it would help the readability hugely.

      Well, that's no harder than looking up what a macro does, and by using a function you can define the types of the arguments and the return value so they get checked, and it avoids sneaky side effects that you can get by using "++" or "&" in a macro so suddenly it can change your parameters. Back in the good old days, using a macro rather than a function call would save you a bunch of clock cycles - in 2017, clock cycles are cheap, and it should be the compiler's job to optimise your code by automatically inlining functions.

    • (Score: 3, Informative) by Thexalon on Saturday December 02 2017, @05:42PM (5 children)

      by Thexalon (636) on Saturday December 02 2017, @05:42PM (#604327)

      Some of the advantages of inline functions over macros:
      1. There are a lot fewer pitfalls with functions than macros. For instance, if I have:
      #define sub(A, B) A-B

      that's easy to mess up with sub(6+5, 6+3), which returns not 2 (like you might expect) but 8. And you can get around that with parentheses and such, but it's an easy mistake to make. By contrast, if you define the exact same concept as an inline function, it's clear. simple, and correct:
      inline function sub(a, b) { return a-b; }

      2. It's a lot easier to fully test an inline function than a macro, in part because of pitfalls like I just described.

      The one place where macros make sense is for the preprocessor adjusting for different C compilers and environments and such.

      --
      The only thing that stops a bad guy with a compiler is a good guy with a compiler.
      • (Score: 3, Informative) by bart9h on Saturday December 02 2017, @06:14PM (4 children)

        by bart9h (767) on Saturday December 02 2017, @06:14PM (#604338)

        #define sub(A, B) A-B

        Giving a obviously, and specially bad, use of something as an argument against it?
        Everyone knows that should be written as

        #define SUB(a,b) ((a)-(b))

        which has none of the problems you mentioned.

        • (Score: 3, Informative) by Thexalon on Saturday December 02 2017, @06:37PM (2 children)

          by Thexalon (636) on Saturday December 02 2017, @06:37PM (#604345)

          You skipped right over this sentence:

          And you can get around that with parentheses and such, but it's an easy mistake to make.

          Good language constructs are those that make it difficult to get wrong and make it easy to catch when you get it wrong. This is like pointing the gun at your own foot - not necessarily wrong, but you're asking for trouble.

          In my example failure, even if you had a little test function, odds are very likely that you did something like this:
          assert(15 == sub(23, 8));
          And you ran the test suite, saw that the assertion passed, and were happy with it because your test covered the code nicely and was correct. And that means that when the bug crept in, this wouldn't be high on your list of things to look at. Especially because a likely result of the error is continuing the program with the wrong value and having a problem in a completely different area of the code because of that incorrect value, rather than a crash right away that you can figure out via a stack trace (and even if you can get a stack trace, the trace points you to where the macro is referenced, rather than the macro itself, so you have to go digging through the header files to find it). Or, even worse, and entirely possible, the incorrect value gets given back to the users as output, and because they either can't or don't double-check with their own calculations, it can even look like the program works correctly even though it's wrong.

          Yes, I used an intentionally trivial example. In a more complex expression, it's more likely this mistake will occur and not get caught until it's a lot harder to sort out.

          --
          The only thing that stops a bad guy with a compiler is a good guy with a compiler.
          • (Score: 3, Insightful) by fyngyrz on Saturday December 02 2017, @11:07PM (1 child)

            by fyngyrz (6567) on Saturday December 02 2017, @11:07PM (#604449) Journal

            it's an easy mistake to make.

            Not if you're actually competent with c, it isn't.

            The argument you're making is essentially "cripple the language (or the use of it) to safety-net incompetent practitioners."

            My argument is: Indulge in some self-improvement. If you don't have a good grasp of how to properly write a c macro, then either don't write them, or go improve your competence with them (seriously, WTF are you, or your employees, doing writing production c code if you don't understand the preprocessor???). For organizations / businesses, pick people with better skillsets (and stop triaging employment by irrelevant crap... it's skill you actually need, so start looking at that, and only that.)

            TL;DR: It's not the c macro system. It's incompetent practitioners.

            • (Score: 2) by coolgopher on Sunday December 03 2017, @12:32AM

              by coolgopher (1157) on Sunday December 03 2017, @12:32AM (#604483)

              While I agree with you in broad strokes, the C macros are very clunky and don't fit into the language particularly well for anything remotely advanced. Then again, in many ways it's its lack of knowledge of C that makes it powerful - you can run rough-shod over all manner of things (not that you should, in 99% of cases, of course).

        • (Score: 2) by crafoo on Saturday December 02 2017, @11:53PM

          by crafoo (6639) on Saturday December 02 2017, @11:53PM (#604466)

          No, that's part of the main point against macros: not everyone knows "#define sub(A, B) A-B" is a bad macro. Most people can write an inline function that subtracts values.

          Also the argument that macros make code more readable is patently ridiculous. It makes it more readable to someone who ASSUMES they know what a macro is doing.

          Anyway, whatever. Programmer arrogance keeps many people employed. They get a kick out of fuzzing your shit macros.

  • (Score: 2, Interesting) by Anonymous Coward on Saturday December 02 2017, @03:57PM (2 children)

    by Anonymous Coward on Saturday December 02 2017, @03:57PM (#604310)
    Obligatory SO. [stackoverflow.com] My favorite:

    Raymond Chen has a really good rant against using flow control macros. His best example is straight from the original Bourne shell source code:

    ADDRESS alloc(nbytes)
        POS     nbytes;
    {
        REG POS rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD);

        LOOP    INT     c=0;
        REG BLKPTR  p = blokp;
        REG BLKPTR  q;
        REP IF !busy(p)
            THEN    WHILE !busy(q = p->word) DO p->word = q->word OD
            IF ADR(q)-ADR(p) >= rbytes
            THEN    blokp = BLK(ADR(p)+rbytes);
                IF q > blokp
                THEN    blokp->word = p->word;
                FI
                p->word=BLK(Rcheat(blokp)|BUSY);
                return(ADR(p+1));
            FI
            FI
            q = p; p = BLK(Rcheat(p->word)&~BUSY);
        PER p>q ORF (c++)==0 DONE
        addblok(rbytes);
        POOL
    }

    • (Score: 2) by hendrikboom on Saturday December 02 2017, @10:24PM

      by hendrikboom (1125) Subscriber Badge on Saturday December 02 2017, @10:24PM (#604434) Homepage Journal

      If you want a different language, you should use a different language.

      If you want to compile to C, that's OK. But then you should parse that different language with its own parser, checking for proper syntax. Hoping that syntax failures will translate to invalid C is not the best way to produce diagnostic messages.

    • (Score: 2) by crafoo on Saturday December 02 2017, @11:55PM

      by crafoo (6639) on Saturday December 02 2017, @11:55PM (#604468)

      hahah wow. That's like an interpretive art project. Sadly, I've seen similar things but not to that level.

  • (Score: 2) by darkfeline on Sunday December 03 2017, @09:49PM

    by darkfeline (1030) on Sunday December 03 2017, @09:49PM (#604806) Homepage

    How about Lisp? Syntactic macros make C preprocessor macros look like a baby pacifier with razors glued on, and hygienic macros are completely safe.

    You can just map C syntax into Lisp syntax, and good riddance, C syntax is absolute shit [c-faq.com].

    --
    Join the SDF Public Access UNIX System today!
(1)