1. 45
    C, what the fuck?? c bowero.nl
  1.  

  2. 13

    Fascinating, I never would have suspected that the backslash would take “precedence” over the single-line comment. The trigraphs are are an interesting historical factoid but I’d have been just as stumped by a comment ending with a regular backslash.

    1. 12

      If that’s really true, then this is the real “WAT?” in my opinion, and making this an article about trigraphs only clouds the message - I kinda didn’t catch the comment-extension issue, because all the time I was thinking only “meh, who sane would even enable trigraphs in the first place?” (Kinda similar level of a practical joke as #define while if in my opinion. I.e. “yes, sure, theoretically there could be some extreme reason to use it in some code; now please revert this change, take your chair to the corner of the room, and write 100 times in your notebook ‘I will never do this again’.”.)

      1. 8

        #define while if

        I would like to thank you for this advice.

        1. 5

          This is a also a lot of fun when someone has a Makefile with either a lot of CFLAGS or uses environmental variables for CFLAGS, because they a simple -Dwhile=if usually breaks everything.

          1. 1

            I like your style.

      2. 6

        Wikipedia mentions another interesting example:

        /??/
        * A comment *??/
        /
        

        This actually is a valid block comment.

        1. 5

          Yes, deleting backslashes before newlines happens very early in the compiler, even before preprocessing: http://port70.net/~nsz/c/c99/n1256.html#5.1.1.2

          The only thing that happens earlier is trigraph substitutions.

        2. 5

          I have to pass -trigraphs to a modern version of gcc before this actually works.

          As soon as I read “trigraphs”, the “WTF” made perfect sense.

          1. 1

            Got any bad experiences?

            1. 4

              It’s long been known that trigraghs are a disaster. No sane person would design that in today. It’s a vestige from days long gone kept around for compatibility reasons. The intense confusion they cause is why GCC disables them by default.

              1. 5

                If you don’t speak up for the trigraph users, will anyone speak up for you?

                (The amusing parts is that EBCDIC does support these characters, but maybe that’s only on i, and z/OS continues to be a nightmare hell dimension…)

          2. 3

            C++ digraphs are fun as well. Have had a few colleagues have a small heart attack when they read:

            If (myfunc() or myotherfunc()) {
            

            Which is valid, just as “and” instead of &&, or bitor/bitand.

            Trigraphs are removed as or c++17.

            Source: https://en.cppreference.com/w/cpp/language/operator_alternative

            1. 2

              Does C++ just implicitly include a header like iso646.h, or are these real, independent operators?

              1. 1

                I feel like these are a lot more used than they should be. Many programmers actually prefer or over ||.

                1. 2

                  I must admit I’m one of those. Even though I know the meaning perfectly, it feels more naturally to have or instead of ||. Not to mention it’s easier to type.

                  1. 1

                    I understand that very well and I think it is not that weird. All modern language support this already. It only is a problem in older systems. Sadly, I work on older systems a lot, so I have to be cautious with modern techniques while developing.

                    1. 3

                      Our codebase is migrating to c++11, but most of our programmers aren’t yet. If your still looking for an internship I could ask around at $job.

                      1. 1

                        People like you are the heroes no one deserves! Thank you so much for helping out. I have already been offered two amazing internships that I prefer however. :)

                        1. 2

                          No problem, I saw it in your LinkedIn, and you’re near. If you’d ever like to do c++ development on coffee machines just message me,

                  2. 2

                    Many programmers actually prefer or over ||

                    Without actual numbers, I would disagree with this, since anecdotally I have very rarely seen this used over multiple projects at multiple companies. It probably varies by company and field.

                    I’m aware of it like a lot of other language features, but choose not to use it myself since it’s never been a convention anywhere I’ve worked and might lead to confusion. Mayhap this might be changing due to the rapid rise of Python instead of Java as the initial language many people learn, and that Python has or but not || and Java has || but not or.

                    One rationale against or at places I’ve worked which also used Ruby was that in Ruby, or actually has lesser precedence than || and can change the meaning of code in subtle, curious, and despicable ways.

                    1. 1

                      I think || is better than or because it keeps the symmetry with |. Same with && and &.

                  3. 2

                    I hadn’t recalled trigraphs for over 20 years! Thanks for the refresher.

                    1. 2

                      !didIMakeAMistake() || CIsWrongHere();

                      If you understand how short-circuit evaluation works, you can understand that this will result in the following:

                      if (!didIMakeAMistake()) CIsWrongHere();

                      Wouldn’t that be if (didIMakeAMistake()) CIswrongHere(); or am I missing something?

                      1. 2

                        (edit to emphasize I support your statement, and you are correct)

                        In f(A) || g(B) g(B) is only evaluated if f(A) is false. If f(A) were true, there is no need to evaluate g(B) since the expression as a whole is going to be True no matter what. This is something to look out for when you have functions with side effects.

                        #include <iostream>
                        
                        
                        int side_effect = 0;
                        
                        
                        bool f(int x) {
                            return x > 2;
                        }
                        
                        
                        bool g(int x) {
                            side_effect = 1;
                            return x > 1;
                        }
                        
                        int main()
                        {
                            int x = 2;
                            if (f(x) || g(x)) {
                                std::cout << "Hello!" << std::endl;
                            }
                        
                            std::cout << side_effect << std::endl;
                        
                            return 0;
                        }
                        

                        You can change the value of x from 2 to 3 to see what happens. Try it out here: https://onlinegdb.com/SJMH13XRB

                        1. 1

                          Yes, you are completely right, thank you.

                        2. 2

                          Out of curiosity, has anyone ever actually used trigraphs in anger? Or maybe seen old code which did?

                          1. 2

                            I imagine that it can be done accidentally with cases like these, but I have never seen them in real, thankfully:

                            printf("What do you mean??!\n");

                          2. 1

                            Similar to a toy gist I made a few years back: https://gist.github.com/wvdschel/2250827

                            Thankfully, C++17 has removed them, and you will get compiler errors if you use sane & modern compilation flags. Not sure about C.