I have heard that it was suboptimal for C to automatically collect garbage -- is there any truth to this?
Was there a specific reason garbage collection was not implemented for C?
I have heard that it was suboptimal for C to automatically collect garbage -- is there any truth to this?
Was there a specific reason garbage collection was not implemented for C?
Objective_C is ANSI C with something like 12 keywords added and a type called id. It has garbage collection. It uses reference counting.
As a language, C was intentionally designed to be really small. It has very few intrinsic operations or features, and most of those reflect the basic instructions found in CPUs. It's often been called a "portable assembly language".
That makes it great for writing portable programs to switch telephone calls around, that run on dinky little computers with very little memory, which is part of what Bell Labs was after in the early 70s when they were first working on C and Unix.
That also makes C great for writing OS kernels, device drivers, and so on. Such executables can't count on having rich, sophisticated runtime environments like garbage collection - or even just dynamic memory allocation like malloc(). That's because they actually form the foundation for those environments, so you run into the "pulling yourself up by your bootstraps" problem.
People have written garbage-collected memory allocation libraries for C. But libraries aren't part of the C language itself, and it's very unlikely something that complex would ever be accepted as part of the standard C libraries. C programmers are a very conservative lot around changes to the standard.
Garbage collection could be implemented for C, though with normal CPU hardware it would be somewhat difficult and inefficient. To really make garbage collection work well, one would need an architecture which used base+offset addressing for everything; the base part of every pointer would be required to always point at the start of an allocated region. Note that if the base were a "selector" rather than a linear address, a 32-bit selector plus a 32-bit offset could access 4 billion objects, each of which could be up to 4 gigs. I would think such a design could be more efficient than 64-bit linear addressing for many applications, since object references and offsets would use half as much cache space as with 64-bit pointers. Using 64 bits just seems like a waste.
BTW, an architecture which used base+offset address for everything would have another advantage over a linear-addressing system: garbage collection could be run concurrently with other operations. The only time garbage collection would have to disturb a running thread would be if the thread tried to access a data object while that particular object was being relocated. Under that scenario, either the relocation attempt would have to be aborted (assuming it was a non-overlapping copy), or the thread would have to wait for that particular object to be copied. A much better situation for real-time code than exists when all threads have to be suspended for GC.
I like what JWZ has to say about C. :-)
C is "the PDP-11 assembler that thinks it's a language".
So, if you look at how you would create a portable assembler, then C looks totally right without garbage collection, for the simple reason CPUs do not have a "garbage collect" instruction.*
(While most other CPU instructions are captured just fine with C to this day, some are not though, like Cs' lack of expressiveness for SIMD operations etc.)
* Yes, I know some of you will find an example to prove me wrong. But in the general case...
The strength (and weakness) of C is that it is small, simple, light weight, and well suited to embedded and systems applications. GC would add overhead, and it would no longer be small and simple. GC for C is simply not appropriate. It's no more complicated than that.
I'm sorry, but saying that C doesn't have GC because it's old or because it was designed for different hardware is a bit ridiculous.
Asking why does C has no GC but other languages do is a bit like asking "why does a hammer have a blunt end while an axe has a sharp end"? Well, languages are tools, and different tools were meant to build different programs with different requirements. Some programs, like device drivers or operating system kernels, have requirements that make it nearly impossible to implement garbage collection while still satisfying them, so a language like C was needed, so C was created.
Just like every other tool, it is the way it is because the problems it was meant to solve forced it to be that way. People who say it was because it was created in the 70s or because of old hardware make it seem like it was completely circumstantial. If this was true, C would have gone away with the 70s, but it's still a popular language.
Besides, gc is very hard to implement cleanly without some sort of runtime system, but C is meant to run on bare hardware.