top | item 46909667

(no title)

smallstepforman | 24 days ago

C’s biggest sins (also inherited by C++):

- unspecified default type sizes. Should have had i8, u16, i32, u64, f32, f64 from the beginning.

- aliasing pointers being restricted by default (ie an alias keyword should have been added). Performance matters. All these benchmarks which show something beating C or C++ are mostly due to dealing with aliasing pointers. C++26 still doesnt have standardised restrict keyword.

There are more but I understand the logic/usability/history behind them. The above points should have been addressed in the 80’s.

discuss

order

krior|24 days ago

Not the error "handling"? The array implementation? The weak type system? The barebones-macro-system? The nearly unuseable standard-library? The standard itself, a 750-page-tome you have to memorize, lest C is allowed to erase your hard drive?

C is sin incarnated.

1718627440|23 days ago

In my opinion error handling in C is great. It forces you to actually think about it, deal with them as close as possible and makes you write it in a forward compatible way. Much better than exceptions were you never no what one might throw in another version.

> The barebones-macro-system?

The CPP is a different language and designed that way so you can use another language that suits you better, most don't do that, because the default is fine.

abcd_f|24 days ago

Arrays decaying to pointers is probably the biggest non-platform specific design oversight.

As you said, it's easy to see where it came from, but it should've been fixed long ago.

1718627440|23 days ago

> but it should've been fixed long ago.

Is 27 years for you not long ago enough? That's more than a generation away and closer to the invention of the language than today.

donkeybeer|23 days ago

Which systems in the 70s or even 90s would have had good hardware support for all these lengths? I think overall perhaps its better that the thing named int works on both the arduino and my amd64 otherwise we might needlessly need to rename all types for each platform to fit the most natural type lengths there. Imagine the 32 bit to 64 bit transition under those conditions.

danhau|23 days ago

All of them, through software implementation, as assembly programmers have done since forever.

You simply choose the integer type that your problem or task requires. If the hardware genuinely can‘t cope with it (performance), you reevaluate your requirements, define new constraints and choose new types. This is basic requirements engineering, which C only made more convoluted.

direwolf20|23 days ago

But it doesn't work. You use an int to hold milliseconds, it works on your machine, and when compiled for Arduino (16–bit int) it wraps around every minute.

1718627440|23 days ago

> - unspecified default type sizes. Should have had i8, u16, i32, u64, f32, f64 from the beginning.

I strongly disagree. The programmer should rather prescribe intent and shouldn't constantly think about what size this should exactly have. Does this variable represent the size of an object, an address, a difference or just a random positive integer? Then use size_t, uintptr_t, ptrdiff_t and unsigned int respectively. Why should I care what exact sizes these are? I hate that modern (system) languages completely throw away that concept. "I want a unsigned integer" "oh, you mean u32" "No! I really mean an unsigned integer."

Also when I do want e.g. 32 bit available, there is no reason, I need to use a suboptimal 32 bit wrapping behaviour when I don't need it. The correct type to use for computation for that would be uint32_fast_t and the implementation chooses what makes sense to use for this.

danhau|23 days ago

How will you know if your integer type is adequate for the problem at hand, if you don‘t know its size?

Choosing the right type is a function of signedness, upper/lower bound (number of things), and sometimes alignment. These are fundamental properties of the problem domain. Guesstimating is simply not doing the required work.

direwolf20|23 days ago

Your problem demands a certain number of bits. Counting milliseconds in a month needs 32 bits. It's not just a random number.