On 2012.5.15 1:41 PM, Jarkko Hietaniemi wrote:
>> Otherwise I haven't come across this problem in other major languages...
>> except maybe C.  And original C has so many design flaws that the list would
>> become useless.
> 
> You will have to back that up somehow, laddie.  And get offa my lawn.
> 
> (I can somewhat understand if your basic premise is simply that "if X
> isn't a modern scripting language, X is flawed", though I wouldn't
> take that as the basic premise.)

Bagging on C is like bagging on Shakespeare.  They were severely limited in
hardware, didn't have a whole lot of prior art to go on and not a whole lot of
people to talk to about it.  Smalltalk, ML, Pascal, Prolog, Lisp and SQL all
came out about the same time, and had solved most of the problems below (in
pieces), so there's only so much I can forgive.

Just because they have an excuse for being flawed doesn't mean modern
languages should be modeled on it.  Since its so pervasive it helps to be
objective about its many flaws.  Most of them are not worth discussing because
nobody in their right mind would consider them these days.

And since you asked, off the top of my head...

Lack of memory protection.
Lack of overflow protection.
Lack of automatic memory management.
Fixed size strings.
Magic data in strings (null character).
Fixed size data structures.
Basic string and memory functions which are unsafe at any speed.
Type system tied to hardware definitions.
    How much hell does 64 bit computing still cause because of this?
Very static but very weak typing (makes it more a chore than a protection).
No arbitrary precision math (still a modern mistake).
Unsafe type casting.
No way to define new types (typedef just renames).
Awful I/O design (I'd need time to make that less subjective).
(non(grammatical(macros))).
Cut & paste libraries (#include).
Basic language features done by a preprocessor.
Awful variable argument function interface.
Strings are just arrays (and the sins you can commit with that).
Arrays are just pointers (ditto).
Generally unportable (much critical functionality is outside the language).
Must declare variables all at once.
switch fall through. (still a classic mistake).
Terrible concurrency support. (fork + IPC and C threads are both nightmares)
Terrible non-ASCII string support. (not even Unicode, just Latin-1)
Byzantine compile and link process.
Lack of exceptions.
Mixed return/error codes.

With enough tools and libraries, and forty years of language upgrades, most of
this can be solved... kinda... but the traps are still there lurking.  If
you're going to wrap C up in tons of library calls and bolt on protections,
why are you coding in C?  Some people realized this and took it to the logical
extreme: use C to write a new language!

C had one purpose: be as fast as possible while remaining vaguely portable.  C
is the hot rod of programming languages.  They stripped out every bit of
convenience and safety gear to make it go as fast as possible and do whatever
the programmer wanted.  Portable assembly (only portable compared to
assembly).  This was great for pushing the limits of hardware 20, 30, 40 years
ago, but now compilers can do a much better job than a human, and safer.

We live in C's shadow: the cultural belief in micro-optimization; its the only
widespread system programming language; and I'd say C's strings, I/O and
memory management are still one of the largest causes of crashes and security
holes.

The idea that you need to strip out all the safeties and conveniences to be
fast is a long, long legacy of C and IMO has held up system programming
language development for decades.  Its finally been broken by languages like
Go and amazing adaptive compiler and virtual machine design, but the idea
still hangs on and still holds us back.


-- 
I am somewhat preoccupied telling the laws of physics to shut up and sit down.
        -- Vaarsuvius, "Order of the Stick"
           http://www.giantitp.com/comics/oots0107.html

Reply via email to