Hacker News new | ask | show | jobs
by wolfspaw 623 days ago
Really liked the trick of defining the struct in the return part of the function.

Array pointers: Array to pointer decay is extremely annoying, if it was implemented as Array to "slice" decay it would be great.

Static array indices in function parameter declarations: awesome, a shame that C++ (and Tiny C) do not support it >/

flexible array member: extremely useful, and now there are good compiler flags for ensuring correct flexible array member usage

X-Macro: nice, no-overhead enum to string name. Didn't know the trick

Combining default, named and positional arguments: Named-arguments/default-arg, C version xD. It would be cool if it was added to C language as a native feature, instead of having to do the struct hiding macro.

Comma operator: really useful, specially in macros

Digraphs, trigraphs and alternative tokens: di/tri/graphs rarely useful, alternatives synonims of iso646.h are awesome, love using and/or instead of &&/||

Designated initializer: super awesome, could not use if you wanted C++ portability. Now C++ supports some part of it.

Compound literals: fantastic, but in C++ it will explode due to stack deallocation in the same line. C++ should fix this and allow the C idiom >/

Bit fields: nice for more control of structs layout

constant string concat: "MultiLine" String, C version xD

Ad hoc struct declaration in the return type of a function: didn't know this trick, "multi value" return, C version xD

Cosmopolitan-libc: incredible project. Already knew of it, its awesome to offer a binary that runs in all S.Os at the same time.

Evaluate sizeof at compile time by causing duplicate case error: ha, nice trick for debugging the size of anything.

4 comments

> Array to pointer decay is extremely annoying, if it was implemented as Array to "slice" decay it would be great.

It's not just annoying, it's the major source of bugs in shipped code. A fix:

https://www.digitalmars.com/articles/C-biggest-mistake.html

I agree wholeheartedly, I really liked your article and fix.

(In fact, I already had your article bookmarked xD, and I’m familiar with and truly admire your work)

>Static array indices in function parameter declarations: awesome, a shame that C++ (and Tiny C) do not support it >/

The first array size is actually always decayed to a pointer, supporting it in a compiler without analysis passes like TCC is just a matter of skipping the "static" token and the size.

> Static array indices in function parameter declarations: awesome, a shame that C++ (and Tiny C) do not support it >/

C++ does?

    void print(const int (&array)[5]) {
      for(size_t i = 0; i < size; ++i)
        std::cout << array[i] << " ";
    }
will fail at compile time if you pass it anything other than an int[5] array
Including an int[6] array, unlike with int[static 5]. This is usually not what you want.
> This is usually not what you want.

very interesting comment considering I'm literally fighting with stupid languages with this kind of permissive rules right now, which definitely just create more bugs (for instance silently dropped values because an upstream API changed, added an element at the end of the list, you updated but since you get no error you now have to go through all the calls to check them one-by-one)

Remember, in C you cannot use anything but a literal constant for the array size. My reference for how useful strict array-size matching can be under such circumstances is standard Pascal (as opposed to Modula-ish Pascals like Borland’s), and the answer there is that it more or less isn’t. Even in C, I’d expect at least some people would actually use things like int(*array)[5], given this syntax is valid even in C89, but in function signatures I’ve literally never encountered it.

If the size could a (type-level) variable, that would be a very different proposition. But variables lead to expressions, expressions lead to functions, functions lead to suffering^W becoming a full-fledged dependently typed programming language—if not an Agda or an Idris then at least an ATS[1]. I’d welcome that, but as far as I can see the ergonomics are very much not there yet for any kind of low-level programming.

[1] https://ats-lang.sourceforge.net/

> If the size could a (type-level) variable, that would be a very different proposition. But variables lead to expressions, expressions lead to functions, functions lead to suffering^W becoming a full-fledged dependently typed programming language

I mean, that's just plain old C++. You could have compile-time expressions operating on compile-time numbers since the 90s ; it's a widely-used feature.

I believe int[6] can still be passed to static 5 but I would have to double check
Pointer decay is not a mistake.

It is what allows to do int * p = arr, and looping on array element with p++.

Keeping array type you would jump beyond the last element at first iteration.

It is, an array and a pointer are different types. There could be ways to convert it to a pointer, but it shouldn’t happen at so many places, implicitly.
Correct. A method to extract a pointer from an array already exists:

  int *p = &arr[0];
The mistake is to allow this:

  int *p = arr;
And yet, coding styles do not prohibit it and there is no compiler that has a warning.