Settings

Theme

Humans should think of sizeof() as a function, says Linus Torvalds

lkml.org

111 points by arjun024 11 years ago · 139 comments

Reader

krylon 11 years ago

IIRC, if the argument to sizeof is a type, the parentheses are mandatory, anyway, so using it like it was a function is more consistent.

I think the reason it is not a function from the standard's point of view is that C does not have any builtin functions (unless my memory totally fails me in this case), all functions have to be either defined locally or #included.

  • netheril96 11 years ago

    Exactly.

    I heard people arguing on the Internet that you should not add parentheses when sizeof is applied to an expression, only a type. I just cannot understand why they bother. Just add a parenthesis and it is always right. Much less cognitive burden.

    • raverbashing 11 years ago

      This is the same people that find it "better" to write JS without the semicolons.

      • tel 11 years ago

        The problem is that without a linter there's no punishment for missing semicolons.

        So really the argument should be that everyone should use a linter.

        • actsasbuffoon 11 years ago

          Agreed. I spend most of my time writing non-semicolon languages like Ruby, Haskell, Scala, Elixir, Clojure, and Python. As a result, I never developed the semi-colon reflex that a lot of Algol-family language users built up. I constantly forget semi-colons even after all these years, and my own inability to remember annoys me.

          I used to skip semicolons in JavaScript because I could never remember to include them. Using a linter with Emacs made it a non-issue; I get a warning in my editor immediately when I miss one.

          PS: I'm really enjoying Rust, so maybe this will be the language that finally forces me to pick up the semi-colon habit.

        • rwallace 11 years ago

          I thought about that regarding semicolons, optional braces, newline placement, consistent placing of whitespace in general; then I decided having the machine tell me where I need to do more work is all very well and good, but what I really want is a program that will do the work for me instead. So I wrote one: https://www.npmjs.com/package/jsclean

        • mcguire 11 years ago

          Oh, there's plenty of punishment. Avoiding the punishment in the difficult part. And you can do that the easy way or the hard way.

          • tel 11 years ago

            Well, sure, but it's probabilistic and delayed punishment. This makes learning habits and ensuring them difficult.

      • Negative1 11 years ago

        I don't believe its equivalent. When I'm writing Scala code in the backend and have to switch to frontend I often find myself omitting the semi-colons but going back and fixing due to self-imposed coding conventions. For Javascript just as in Python or Scala, semi-colons are optional for a good reason.

        • bigtunacan 11 years ago

          We would all be better off if semi colons had just been required in JavaScript. The problem is that semi colons are not actually optional in JavaScript. Instead JavaScript use ASI, automatic semi colon invasion, where the compiler attempts to determine where semi colons should go. Unfortunately the rules are complex, prone to certain errors, and I can't rely on everyone I ever work with understanding all of those rules. For all of these reasons if you are writing JavaScript you should just use semi colons.

          • tauchunfall 11 years ago

            >Unfortunately the rules are complex, prone to certain errors, and I can't rely on everyone I ever work with understanding all of those rules.

            Are they really complex? This recently released version 4.0.0 of the JavaScript Standard Style [1] suggests to never start a line with "(" or "[". This rule looks even simpler than the rules of operator precedence.

            [1] https://github.com/feross/standard

            Update: Now I learned about the JavaScript Semi-Standard Style [2] which accually enforces semi-colons. Quite hilarious.

            [2] https://github.com/Flet/semistandard

            • bigtunacan 11 years ago

              They are complicated enough; and different enough from other languages that they lead to unexpected behaviors. It is just easier to say, "everyone must use semi-colons". Then I can add linting into our build process and reduce risk of bugs.

              One quick example is the very contrived example that follows.

              return {a:1, b:2}

              That is valid JavaScript. It is evaluated as an empty return and an unreachable expression. Probably not what was intended.

              I've sent copies of the rules to people and explained them numerous times, but at the end of the day it is more productive to just use them and move on to something else IMHO.

          • rhaps0dy 11 years ago
            • skue 11 years ago

              If you have an argument to make, then make it.

              The previous poster didn't say he was unwilling to learn JS semicolon rules, he was saying he couldn't trust everyone he ever works with to learn them. Replying with an accusation of FUD and a link to someone ranting that it's unprofessional for JS devs to not know these rules is unnecessarily inflammatory while missing his point.

        • raverbashing 11 years ago

          Well, semicolons may be optional in Python but the official python style strongly recommends agains (needing to use them)

          It's not about forgetting them once in a while, it's about playing a game of "needs a semicolon or doesn't" which increases the (already high) number of things the developer needs to worry about

        • netheril96 11 years ago

          In Python you usually don't add semi-colons, and it will bark when your intention is unclear.

          In javascript you may omit semicolons, but the interpreter will guess your intention when it is ambiguous and it will probably guess it wrong.

      • woah 11 years ago

        Do semicolons make the code run faster? What is the advantage exactly? There is no downside to leaving them out.

        • Igglyboo 11 years ago

          AFAIK the only "benefit" to semicolons is that you can put multiple statements on the same line.

  • weinzierl 11 years ago

    In C there are no functions that take a type as argument.

    So

       sizeof(type)
    
    is a special case anyway.

    I'm all for using sizeof like a function, but that doesn't make it consistent. sizeof is just a special syntactical construct.

    I like to think that sizeof is called an operator just for syntactic convenience much in the same way as typedef is a storage-class specifier.

    • masklinn 11 years ago

      And you really shouldn't use it with a type if you can avoid it anyway, it makes code brittle e.g.

          int *foo;
          // code
          foo = malloc(sizeof(int));
      
      a few months later, change foo to be a double. Code still compiles, no warning, but you're allocating half the memory you need.
      • xamuel 11 years ago

        This is a really great example why you SHOULDN'T think of sizeof as a function. If sizeof were a function, the code

          int *foo = NULL;
          foo = malloc(sizeof(*foo));
        
        would be undefined behavior (dereferencing NULL)!
        • Kranar 11 years ago

          Dereferencing a null pointer is legal in C. It's the conversion of a null pointer from from an r-value to an l-value that's illegal, which does not happen in that snippet of code.

          That's why it's perfectly legal in C to do this (&*foo), even if foo is a null pointer.

          • masklinn 11 years ago

            > Dereferencing a null pointer is legal in C. It's the conversion of a null pointer from from an r-value to an l-value that's illegal, which does not happen in that snippet of code.

            And it does not happen in that snippet of code because sizeof is nothing like a function.

      • imglorp 11 years ago

        Which is why it's nice to lift stuff out into typedefs. It centralizes them (DRY principle) and avoids this issue.

            typedef int thing_t;
            ...
            thing_t *foo;
            // code
            foo = malloc(sizeof(thing_t));
        • viraptor 11 years ago

          Why is that better than just getting `sizeof(* foo)`? Even with typedef, I can see this happening in the future:

              typedef int thing_t;
              ...
              thing_t *foo_internal;
              thing_wrapper_t *foo;
              // code
              foo = malloc(sizeof(thing_t));
          
          If you do:

              foo = malloc(sizeof(*foo));
          
          That's at least always on the same line.
        • userbinator 11 years ago

          That just makes it more verbose.

          This, on the other hand, always allocates one object of foo's pointed-to-size, whatever its type:

              foo = malloc(sizeof(*foo));
        • dllthomas 11 years ago

          As an aside, I think nearly any time you want a typedef, it's worth wrapping it in a struct.

              typedef struct { int value; } thing_t;
          
          That way the compiler catches it when you try to pass the wrong thing (at least, more of the time).
        • dllthomas 11 years ago

          DRY is good, but making the structure of your code reflect the actual semantics you want is better. What you want is to allocate space for foo. So write that.

        • crazy2be 11 years ago

          Well, in this (simple) case you can just do

              int *foo;
              foo = malloc(sizeof(*foo));
          
          And avoid the brittleness mentioned.
    • ksherlock 11 years ago

      There are standard macros (va_arg, I'm looking at you) that take a type as an argument.

  • barrkel 11 years ago

    Another oddity of C that amuses me is the do/while loop without braces:

        int i = 4;
        do
           printf("hey\n");
        while (--i > 0);
    
    Even though do/while is a keyword bracketing pair in C, it still only lets you use a single statement (because nested whiles). So everybody uses braces, and thus it looks quite disturbing without them.
    • kevin_thibedeau 11 years ago

      Its not so disturbing when you consider that braces aren't special cased in the C grammar. They group statements so they can be used together where a statement is needed. From the grammar's perspective the "normal" way is without braces. It's just that all the C-alikes have gone a different direction with the way braces are parsed leading everyone to regard the original behavior in C as ugly warts.

      • tmuir 11 years ago

        for, if, and while without curly braces for single statement blocks are easily one of the worst things about C. It bites you in the ass every time. The balance between its utility and its capacity to cause bugs is so one sided, I don't understand why it's even taught to beginners. If you are teaching a new programmer that saving keystrokes is important, you're on the fast track to creating a shitty programmer.

        • JoeAltmaier 11 years ago

          That's pretty severe. Written with spacing, its really pretty clear what is meant by

             if (condition)
                Foo(x)
          
          Braces are, in my opinion, an unfortunate necessity in some cases. They are a much larger cause of error than NOT using them ever could be.

          An ideal IDE would make blocking visible (background tone change etc), and braces could be emitted automatically by the IDE without ever cluttering up the code shown to the programmer.

          • tmuir 11 years ago

            But tying everyone to a single IDE is never going to happen. The language is out there. It's going to stay backward compatible forever.

            How could the presence of braces cause a worse error than no braces? Code compiles when you completely omit braces but put more than one statement underneath. The error is logical, not syntactical.

            But if you have an open brace without a matching close brace, that's a compile error. What other error are you referring to?

            How can you know that you won't add more statements to the block? Why have a special case at all? For me it's just become muscle memory to add the braces. It's a risk with exactly zero upside to omit braces.

          • Igglyboo 11 years ago

            The only problem with this is if/when someone comes along and doesn't notice the missing braces and does

               if (condition)
                  Foo(x)
                  Bar(x)
            
            Expecting Bar(x) to be part of the conditional. This can and does happen.
            • JoeAltmaier 11 years ago

              I hear folks say that, but don't encounter it in the wild. Maybe once in 20 years so far. That construct, reading it just now, just screams out at me "Indentation error!"

              Anyway it nicely illustrates the need to get braces out of there altogether. The programmers' intent is obvious; let the IDE 'make it so' by emitting braces in the generated code.

              • csixty4 11 years ago

                > I hear folks say that, but don't encounter it in the wild. Maybe once in 20 years so far.

                It was the cause of the "goto fail" SSL bug that affected both of Apple's operating systems last year: https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-got...

                So I'd say it's rare, but it happens. And when it happens, the effects can be pretty big.

              • jotux 11 years ago

                I've never seen (in code I've worked on)

                    if (condition)
                        Foo(x);
                        Bar(x);
                
                But I have seen

                    if(condition1)
                        if(condition2)
                            if(condition3 && condition4)
                                Foo();
                
                This upset the old ARM compiler I was working on and it decided to skip some of the conditions. I fixed the bug, related to this code, by adding braces:

                    if(condition1)
                    {
                        if(condition2)
                        {
                            if(condition3 && condition4)
                            {
                                Foo();
                            }
                        }
                    }
                
                So this is why I always put braces to define scope. Although, in general, both of these types of bugs are uncommon.

                Honestly, the more pervasive problem that comes up is the eventual addition of new code adds noise to diffs. Like if I have a condition with a single statement

                    if (condition)
                        Foo(x);
                
                And I add something to it, I have to add braces and it pollutes the diff with stuff that isn't really related to what I'm changing.

                    if (condition)
                    {
                        Foo(x);
                        Bar();
                    }
                • dllthomas 11 years ago

                  "This upset the old ARM compiler I was working on and it decided to skip some of the conditions."

                  Do what you need to work around a known compiler bug, of course, but that is definitively a compiler bug. The meaning is unambiguous and consistent in the C standard and every implementation I've encountered. I'm not comfortable with the assertion that changing your coding style here makes you less susceptible to compiler bugs in general.

              • barrkel 11 years ago

                I agree with you - I can count the number of times I've seen it in my life on one hand - but ever since the Apple bug, lots of people use it as a club to hit people over the head with, to enforce braces everywhere.

                There seems to be a logical error to me. An indentation mistake - something that can be caught trivially by a linter - is not significantly different by nature than any other single-character mistake, like an incorrect constant or misspelled identifier (harder to find with a linter). But because it was at the root of a specific flaw, it's become larger than life.

          • gumby 11 years ago

            non-bracket is useful and informative in some cases when used properly (your local style guide takes precedence of course). I would never write

               if (condition)
                  Foo(x)
            
            for the reasons you said. But it can be very useful for a block of "single liners":

              /* clean up input before passing it to flaky_external_module() */
            
              for(; !isspace(*p); ++p); 
              if (!isdigit(*p)) return INPUT_ERR;
              for (char *i = p; *i; i++) *i = toupper(*i);
              ...
            
              flaky_external_module(p);
            
            
            Basically a small block (that pretty much fits in your fovea) that does a bunch of minor tasks. Spacing them out would actually confuse the code.
            • tmuir 11 years ago

              I contend that the brackets always make the code more readable, without exception. It's the normal case. All other variations make you think "something special is happening here, I'm going to have to parse this carefully". The for with a semicolon at the end is easy to overlook. The return in the middle of a function in the middle of a line is easy to overlook.

              Spacing code out makes it more readable and maintainable, not less. It brings consistency, and it is more prepared for the inevitable change. I think maintenance is the driver of all code style. When you make tight one liners or forgo braces, or use the ? And : operators instead of if and else, you're not really saving time, you are deferring work, in a lot of cases to another programmer.

              • gumby 11 years ago

                Well, as I said, these determinations are up to the house style.

                I prefer that blocks of code hold together -- think of them as paragraphs. Spacing each sentence of a paragraph out is similarly confusing. But as you say, YMMV.

                I find return is_valid(result) ? result : ERR_CODE; common and clear, but perhaps you don't.

                I do think that any style guide should forbid while and do..while simply because for has become by far the looping construct of choice in C.

                In all cases the point should be correctness and clarity, not showing off that you use unusual language features.

    • gumby 11 years ago

      > Another oddity of C that amuses me is the do/while loop without braces: [...] > Even though do/while is a keyword bracketing pair in C, it still only lets you use a single statement (because nested whiles).

      Ah, but don't forget you can still use the comma operator, so get several statements in before the semicolon:

          int i = 4;
          do
             printf("hey"), printf("Jude.\n");
          while (--i > 0);
    • cygx 11 years ago

      it looks quite disturbing without them

      Remove the newline and it looks ok to me:

          int i = 42;
          do printf("hey\n");
          while (--i > 0);
      
      Another possibility would be:

          int i = 42;
          do printf("hey\n");
              while (--i > 0);
      • viraptor 11 years ago

        Oohh... this would be so good for the underhanded C contest! Just mix is up with the comments which make the `do` look like (assuming good actor) an accidentally wrapped comment.

            /* The following code does something, so here's the
            // explanations of what happens. And here's what we actually
            */ do
            printf("hey\n");
            
            /* And now just count down */
            while (some_check(--i));
        
        Now spot that in a large file of real code!
        • pierrec 11 years ago

          Sneaky. Most syntax highlighting would make it stick out like a sore thumb, but still, sneaky.

      • gpvos 11 years ago

        Just looking ok is not the point. I would prefer a match between how it looks and what it does...

  • eliben 11 years ago

    > it is not a function from the standard's point of view is that C does not have any builtin functions

    The problem with sizeof is that is should be able to accept a type as an argument. No function in C can do that, according to the standard C grammar.

    Somewhat similarly, the standard va_arg is a macro, not a function, also because it accepts a type.

Udo 11 years ago

I'd like to confess that I'm one of the return() people, and I also do if() even in cases where the language doesn't require it. This behavior isn't borne out of confusion about what is and what isn't a special language construct. Rather, it helps me prop up the illusion that programming is about using a few simple primitives instead of being the chain of compiler directives it actually entails - it's an esthetic choice if not always a logical one.

The thought that if() could just be a lazily-evaluated function taking a code block argument, and that return() could be a way of marking the end result of an expression somehow pleases me.

I think the different expectations about sizeof() come from the artificial distinction between operators and functions, the implication being that in a compiled language the sizeof operator would be a compile-time construct, or barring that, at least a behavior of the type system. On the other hand, there are tons of compiler intrinsics in C/C++ that look exactly like functions but aren't.

  • sedeki 11 years ago

    Doesn't `if` always require parenthesizes?

    • Udo 11 years ago

      No, not always. Not in Go, or in Rust, or Ruby, for example. The assumption being in these languages that if is followed by an expression and that expression is parsed to its natural end anyway - but this only works if the syntax allows for that end to be found without ambiguity.

      • krylon 11 years ago

        In Go, however, go fmt will remove the unnecessary parentheses. I was very annoyed at first, when I saw this, but I got used to it.

        • mcguire 11 years ago

          Does it generally do this in expressions, based on operator precedence, or is it limited to the outer parentheses on selected statements?

          • krylon 11 years ago

            I am not an expert, but I think it only removes the outermost ones. The major task of the tools is indentation and placement of curly braces.

    • elisee 11 years ago

      Yes, in C, but I believe Udo was talking about other languages (like Go for instance)

      > and I also do if() even in cases where the language doesn't require it

      This sentence could be parsed in multiple ways though :)

    • nikai 11 years ago

      Not even in C. You can have an if condition that is actually a macro that expands with parentheses. For example the macros in ctype.h, so you can actually write

        if islower(c) {
            (..)
        }
      • cygx 11 years ago

        That's not portable, though: A comforming implementation may very well implement islower as a function call, and you should treat is as such.

      • raverbashing 11 years ago

        Yeah, but macros are not really part of the language, they're more a writing aid than anything really.

        So, for the sake of good practices, write if with parenthesis.

      • olavk 11 years ago

        That is cheating!

    • zoul 11 years ago

      Not in all languages. For example, Go and Swift don’t require it.

Negative1 11 years ago

I respect Linus greatly but the way he to talks to his fellow 'humans' is insanely confrontational, rude and disrespectful. It overshadows his arguments (which are usually very good) and throws people on the defensive. I'm grateful for all he has accomplished and shared with us but I imagine working with him is 'hell'.

  • return0 11 years ago

    I quite enjoy his style, but i understand it's not for the newer "easily triggered" generations

  • moonbug 11 years ago

    Agreed. Not sure which is worse - that he's a terrible role model, or that he's proud of that fact.

  • douche 11 years ago

    I would imagine once you get used to him and thicken your skin up a bit, it's no big deal.

    Hell, a little salty language and telling people they're being idiots when they are being idiots is not a bad thing. The best machinists and millwrights I've worked with were like that, and it was a good thing - you don't have time to ask politely when there are steal beams or a two-ton electric motor swinging towards you.

    C can be almost as dangerous :-)

    • twerquie 11 years ago

      He literally says that those who disagree with his code style should be shot. That's completely unacceptable language to use and makes him sound like he hasn't mastered English. I'm not sure anyone should take c-language style tips from such a boor.

      • infamouscow 11 years ago

        Most systems programmers I known share similar views.

        The rational is that you should only be working on systems-level code if you have an exceptional understanding of computers, the code base, and the repercussions of changes. If your understanding of multithreading isn't flawless then you should not be working on the OS scheduler, at all. And for a programmer working at this level to not recognize the importance of code clarity is to undermine the responsibility that goes with it.

      • Igglyboo 11 years ago

        It's called hyperbole, it's quite common in english.

  • topkekz 11 years ago
    • mcguire 11 years ago

      Keep in mind: that's the dipshit that thinks he's the avatar of Pan.

    • tormeh 11 years ago

      Making others feel warm and fuzzy is one of the most important things in life. I don't like that it's downplayed.

gpvos 11 years ago

I used to write

    return (0);
I.e., with a space. I'm not sure if someone ever told or recommended me to do this, but the reason I did this was consistency with other C statements, because all C statements that take some kind of expression as a parameter (if, for, while) require it to be surrounded by parentheses. So it seemed logical to me to do the same with return. I've stopped doing it now, although some of the old code still lives.

I've seen code by others where there was always a space between the function name and its arguments. That was ugly, and really confused a function call with a statement.

  • krylon 11 years ago

    I find parens around a return value/expression slightly annoying, but not annoying enough to have a debate over it. It doesn't make the code harder to read, IMHO.

    Whitespace between a function name and the arguments is significant, however, because with a function-like macro, there must be no whitespace between the name and the opening parenthesis. I've seen the following code in production code, for example:

      #include <stdlib.h>
      #define free(x) free(x), x = NULL
    
      free(ptr1); // Macro
      free (ptr2); // Call free(3) directly
    
    (Whether or not such a macro is good idea is a different question entirely, the point is that you can prevent such macro-expansion by using whitespace. Aesthetically, I find it very disturbing, though.)
    • rwallace 11 years ago

      You do need to omit whitespace between the name and the opening parenthesis when defining a functionlike macro, but it doesn't matter when you're calling it.

      • krylon 11 years ago

        I furiously looked at the C standard (C99, anyway) and the documentation to the gcc preprocessor, and have to admit somewhat embarassedly, that you are right. The gcc preprocessor documentation clearly states:

        > "If you use the macro name followed by something other than an open-parenthesis (after ignoring any spaces, tabs and comments that follow), it is not a call to the macro, and the preprocessor does not change what you have written."

        Thanks for pointing this out to me!

tvb 11 years ago

Makes a good C interview question:

    char  c;
    short h;
    int   i;
    char *s;
    1 = sizeof (char)
    2 = sizeof (short)
    4 = sizeof (int)
    4 = sizeof (float)
    8 = sizeof (double)
    1 = sizeof (c)
    2 = sizeof (h)
    4 = sizeof (i)
    4 = sizeof (s)
    4 = sizeof &c
    1 = sizeof c
    2 = sizeof h
    4 = sizeof i
    4 = sizeof s
    1 = sizeof *s
    4 = sizeof &main
    4 = sizeof (sizeof (i))
    4 = sizeof (sizeof i)
    4 = sizeof sizeof i
    4 = sizeof sizeof sizeof i
from: http://leapsecond.com/tools/size1.c
moonbug 11 years ago

"Quite frankly, if you do this, you should be shot. "

Ah, yes. No comment from Torvalds is complete without a gratuitous ad hominem.

  • loup-vaillant 11 years ago

    This is not an ad hominem argument. This is merely blowing things out of proportion. This would be ad hominem (and non-sequitur):

    "You're watching dancing bunnies, and you dare suggest we should remove the parens after sizeof?"

    Attack on the person (watching dancing bunnies), used to discredit an unrelated opinion (parens after sizeof).

  • falcolas 11 years ago

    To be fair, he's referring to the code `sizeof(*p)->reference`, in which case I'd probably shoot the writer too.

  • sfk 11 years ago

    I'm sure he'd appreciate a memo from Sam Altman about gratuitous negativity.

Chathamization 11 years ago

I first learned that sizeof was an operator when I was confused about how it dealt with arrays compared to functions. After I learned it was an operator and not a function things made sense and were (relatively) consistent again. Several commentators here have given other examples where you will be completely thrown off if you believe that '"sizeof()" really is a function.'

The problem with "lies to children" is that they can pile up to the point where people end up becoming completely confused about what's actually happening. As the internal inconsistencies mount, the "simple" lie starts to become a lot more complex than the "complicated" truth.

nmj 11 years ago

> Here's an example of a really bad use of "sizeof" that doesn't have the parenthesis around the argument: sizeof(*p)->member. Quite frankly, if you do this, you should be shot.

Good ol' Linus

mburns 11 years ago

(2012)

mattkrea 11 years ago

Just as annoying as people not using parens with "typeof()" in JavaScript.

tormeh 11 years ago

Why is this important?

wz1000 11 years ago

> "return()" is in no way a function.

Ah, but in Haskell, `return` is a function, though it shares only a few similarities with with its counterpart in C-like languages.

However, when using continuations or a continuation passing style, the continuation is a function that behaves almost exactly like traditional return when called!

    (define (multiply x y return)
      (return (* x y)))
progrn 11 years ago

But, I cannot get a function pointer to it, right?

soup10 11 years ago

What kind of monsters don't use parentheses on sizeof. Is it the same guys that put { on new lines and have giant comment templates for every one line function.

  • MrBuddyCasino 11 years ago

    Ah, to join the bikeshedding: { on newlines make imho more sense, the block of code is visually balanced that way. We have high-res screens now, no reason to pretend we're still on 80 char terminals.

    But work long enough in either one of those styles, and the other one will start to look strange.

    • heisenbit 11 years ago

      We got higher resolution and with it not taller but wider screens. So following your reasoning the { should be on the right ;-)

    • Retra 11 years ago

      What advantage does 'visually balanced' give? That's like saying the letter A is better than B because it's 'stands up better.'

      Indentation is how you should identify blocks.

      • xamuel 11 years ago

        Indentation to identify blocks can break down in things like switch statements:

        switch( c ) {

           case 'A':
             simple_stuff();
             break;
        
           case 'B': {
             int temporary_variable = 0;
             complex_stuff( temporary_variable );
         }
        
        To me, the advantage of braces on newlines is it makes it extremely easy to tell where blocks start and end---whether you're using your favorite IDE, or reading the code on a blog, or reading the code with "cat". I actually think it's a case where Python has the design advantage on C (since if you do braces-on-newline consistently enough, you end up duplicating python but with superfluous braces added in).
        • JoeAltmaier 11 years ago

          Fundamentally, the problem is that braces are needed at all. Humans are bad at matching them up, so they don't match the humans' intention when indenting. Confusion.

          It's all backward. The IDE should SHOW you the blocks somehow (background tone changes etc), and let you edit the blocking explicitely. If they look wrong, you select and hit a key. Now you're in agreement with the compiler.

          • MrBuddyCasino 11 years ago

            Yeah, this is one thing Python got right. You should indent anyway, and then the curly braces aren't needed anymore.

            I don't know what the point is in pretending IDEs or advanced text editors don't exist.

        • douche 11 years ago

          I'm not seeing what the issue here is, besides that this won't compile because of mismatched braces. There is no need to put braces around the contents of a case block. Unless I'm switching on an enum, I rarely find a compelling reason to use switch/case, and there's usually a cleaner way to do it.

          • dllthomas 11 years ago

            "There is no need to put braces around the contents of a case block."

            There is here.

            In some dialects, you can only declare a variable at the start of a block. From the perspective of the compiler, a "case block" isn't actually a block, just stuff between labels. In order to declare temporary_variable, it may be necessary to put the braces, and it is probably best practice as temporary_variable may otherwise be exposed to later cases (and in C++, a jump over a variable declaration seems to produce an error).

  • michaelmior 11 years ago

    { on new lines seems to have dominated the majority of code I've worked with although I've always preferred putting it on the same line myself.

    • harkyns_castle 11 years ago

      Most C++ codebases I've seen have the brace on a fresh line, most Java codebases at the end of the line (at a guess born of the Sun guidelines and default Eclipse formatting perhaps). I started with the former, but prefer the latter now.

      To me its more about conserving an extra bit of vertical space... I like my methods/functions quite compact. In the past I liked the balanced nature of the braces though.

      Makes absolutely no appreciable difference though of course, as long as you don't get into a formatting war with your team.

    • pivo 11 years ago

      I put it on the line that makes the code following it the most clear

      • MrBuddyCasino 11 years ago

        How do you handle auto-format? If a rules doesn't survive that, its not practical, at least for me.

        • pivo 11 years ago

          We don't use auto format for one because as far as I know it's not available for our languages (objective-c and swift)

        • vidarh 11 years ago

          I've never met an auto-formatter that I haven't hated the output of enough to not use it.

          • MrBuddyCasino 11 years ago

            Which ones would that be? The Eclipse one has a million knobs and twiddles, and is bearable in 95% of the time after fiddling with them a lot, which I'm okay with.

            • vidarh 11 years ago

              I must admit I haven't used Eclipse's auto-formatter because I've never met an IDE that haven't made me want to kill myself, and Eclipse is at the top of the list of IDE's I have never been able to stand more for than 5 minutes.

lazzlazzlazz 11 years ago

Who the hell doesn't think of `sizeof` as a function?

  • noselasd 11 years ago

    It's an unary operator, with 2 forms:

       sizeof(type)
    
    or

      sizeof expression
    
    but e.g. unlike a function, it doesn't evaluate the expression.

        sizeof(my_function()) doesn't call my_function.
    
        sizeof(a = 12) doesn't assign 12 to a.
    • lazzlazzlazz 11 years ago

      That's a language design choice - not a conceptual argument.

    • Retr0spectrum 11 years ago

      So is "sizeof(a = 12)" equivalent to just "sizeof(a)"?

      • hebdo 11 years ago

        Well, `a` could overload the "=" operator, in which case you would get `sizeof(a.operator=(12))`. But as far as pure C goes I believe you are right.

        Edit: Via the C99 spec (http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf).

        The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

        The type of an assignment expression is the type of the left operand unless the left operand has qualified type, in which case it is the unqualified version of the type of the left operand.

        So it is indeed the case that `sizeof(a = 12)` is equivalent to `sizeof(a)` in the C world.

        • to3m 11 years ago

          An interesting result of this (I suppose...) is that if a macro expands an argument twice, and one of those times is an operand for sizeof, you don't need to mention the double expansion in the documentation.

  • Luc 11 years ago

    I learned C from 'Kernighan & Ritchie', where it's never referred to as a function but as a compile-time operator. I've never thought of it as a function.

  • _lce0 11 years ago

    Well it's an operator, and algebra said all them are just functions... Just like `+` is a function

    Anyways not all those writing code have CS background

    • weland 11 years ago

      Except algebra said that about algebraic functions and operators.

      I know a CS major who insisted in pointing out the same thing. He was extremely surprised when dragons hatched from his eggs instead of the chickens he expected. It was a really heated event. He barely escaped -- and then ranted for several weeks how they were really just eggs and couldn't explain what happened.

    • masklinn 11 years ago

      Except sizeof is a compile-time operation, not runtime. If sizeof were a function,

          int *foo = malloc(sizeof(*foo));
      
      would make no sense.
      • barrkel 11 years ago

        Compile-time functions are a thing. Not in C, but in other languages, including C++.

        This all comes down to what you think "function" means. If you're living in a C bubble, of course sizeof isn't a function. If you have a wider mapping (!) for the word, then it is a kind of function.

        • mcguire 11 years ago

          If you think everything called a "function", in every context, is the same thing, you are going to have a very bad day.

      • userbinator 11 years ago

        In C99, sizeof is compile-time only if VLAs are not involved.

        In C89, sizeof is always compile-time.

      • rdc12 11 years ago

        So in practice it works more like a C Macro then a C function?

        Edit, except it doesn't treat arguments the same, so no.

        • cygx 11 years ago

          It's neither:

          sizeof belongs in its own category of unary compile-time(-ish) operators, whose only other member is _Alignof.

          If you're so inclined, you might add _Generic and _Pragma to that mix as well, but they aren't really a close fit.

kazinator 11 years ago

Yes, return can be a function. Torvalds hasn't heard of continuations, obviously, where we "return" from a function by invoking a continuation.

We can justify writing return (expr); using the same arguments that justify the sizeof (expr) convention.

The thing is that in C, return isn't a function; there are no continuations.

Similarly, sizeof is an operator, which doesn't reduce its argument expression to a value.

If we are going to make coding conventions based on pretending that C is a different language in which sizeof is a function, then pretending return is a function is also fair game.

  • hueving 11 years ago

    He is talking about C. Continuations are irrelevant.

    • kazinator 11 years ago

      That point is clearly made in the comment you're replying to, with the additional point that if we are talking about C, then sizeof is an operator, not a function. It doesn't require parentheses, except when its operand is a type expression. No well-considered coding convention requires superfluous parentheses with sizeof, and there are good reasons to ban them.

      We should prefer code like:

         type *ptr = malloc(sizeof *ptr);  /* no parens */
      
      to

         type *ptr = malloc(sizeof (type));
      
      In general it's often better to base sizeof on an ordinary expression rather than a type expression.

      If we don't use superfluous parentheses on sizeof, we can then look for sizeof followed by an open parenthesis to look for code where sizeof is applied to a type expression.

        sizeof (type)
      
      means "produce me a size_t value based on some arbitary type, without checking that it's related to anything in the surrounding code". It can be as dangerous as a (type) cast.
  • newuser88273 11 years ago

    Scheme has come up with the idea of pretending that an undelimited contination is a function, which is somewhat true-ish... in the degenerate sense of a function with empty domain.

    This is fine for Scheme, which is an expression language, so every method of invoking a continuation would, syntactically, be an expression anyway.

    In C, which has statements, making return look like an expression is somewhat pointless. It doesn't matter whether C "has" continuations (and it arguably has) or not.

  • anonbanker 11 years ago

    Why shouldn't return be considered a function?

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection