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.
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.
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.
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
Please stop spreading FUD.
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.
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.
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.
In javascript you may omit semicolons, but the interpreter will guess your intention when it is ambiguous and it will probably guess it wrong.
So really the argument should be that everyone should use a linter.
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.
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.
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. typedef int thing_t;
...
thing_t *foo;
// code
foo = malloc(sizeof(thing_t)); int *foo;
foo = malloc(sizeof(*foo));
And avoid the brittleness mentioned. 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.This, on the other hand, always allocates one object of foo's pointed-to-size, whatever its type:
foo = malloc(sizeof(*foo)); 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). int *foo = NULL;
foo = malloc(sizeof(*foo));
would be undefined behavior (dereferencing NULL)!That's why it's perfectly legal in C to do this (&*foo), even if foo is a null pointer.
And it does not happen in that snippet of code because sizeof is nothing like a function.
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.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); /* 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! 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.
if (condition)
Foo(x)
Bar(x)
Expecting Bar(x) to be part of the conditional. This can and does happen.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.
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.
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();
}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.
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.
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.
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.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.
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.
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);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.