Peter Kraft’s Post

View profile for Peter Kraft

Co-founder @ DBOS, Inc. | Build reliable software effortlessly

C is Not a Low-Level Language That sounds pretty scary, doesn’t it! C is the lowest-level language most of us know. If it isn’t “low-level” enough, then what is? This is a really cool article because it invites us to take a close look at what “low-level language” means. If we think about it, a low-level language should be “close to the metal.” It should have as few abstractions as possible between the programmer and the computer. Now, C feels like it’s close to the metal. After all, you’re manipulating memory directly with primitive operators and none of those fancy abstractions you’d find in a more modern language. And that’s because C was close to the metal–50 years ago. C was designed as a truly low-level language for DEC’s PDP-11, one of the most popular computers of the 1970s and 1980s. But computers have changed a lot since then! The first fundamental change in how computers work is instruction-level parallelism. C assumes that all instructions in one thread of your program execute sequentially in order. But that hasn’t been true for years! Modern CPUs are tremendously sophisticated parallel processors that inspect adjacent instructions and try to run as many as possible in parallel, even speculatively executing instructions that may never run. And most modern CPUs contain many such processors, so fast programs must be truly parallel, with many threads–something C doesn’t make easy. The other fundamental changes in how computers work is hierarchical memory. C assumes that memory is a big array that you can randomly index into. But modern architectures have multiple layers of cache between memory and the CPU, and random indexes into memory are slow. To make C run fast, you have to be aware of how the cache works and use it as much as possible, but C provides absolutely no help with this. So how is C so fast if it isn’t a low-level language? The answer is tremendously sophisticated compilers. A modern compiler, like Clang, runs to 2 million lines of code that was built by hundreds of developers over decades. All this code is necessary to perform dozens of optimizations to fundamentally change how your C code executes so it can be fast on a modern processor, while keeping (roughly) the semantics you want. The resulting machine code is extremely fast, but almost unrecognizable compared to your original program. And if you want the fastest possible code, you have to deeply understand what these optimizations do and how your computer really works–because your computer is not a fast PDP-11, and C is not a low level language.

  • No alternative text description for this image
Peter Smith CEng

Principal Electronics Engineer at Chess Dynamics

1w

The vast majority of microcontrollers still have the same fundamental architecture as The PDP-11 so C can be a natural fit. It is not the only language suitable but it has advantages in this case. It is rare to have multiple execution units in microcontrollers. Some have MMUs, admittedly. Modern microprocessor architecture has indeed evolved significantly. Writing device drivers for microcontrollers requires direct access to the internal registers.

Gur Stavi

Software Architect at Toga Networks

1w

The assembly language that CPU provides to the user is the same single threaded assembly from 50 years ago. It changed from 16 to 32 to 64 bits but it is still the same. C language is the lowest you can get on these CPUs. No matter how much internal parallelism exists, the only thing that matters is the assembly interface. The one thing that is poorly utilized is vectorized assembly instructions: mmx, sse, avx, etc. The optimizer side of the compiler does evolve and so is the way that we, C developers, write software.

Is there really a high and low level language or is it more of a range? If I was to say C is a low level language, some may agree, others disagree, if I was to say it's more low level that C# or javascript, I think everyone would agree

Like
Reply

> C assumes that all instructions in one thread of your program execute sequentially in order.  But the machine language instruction sets themselves maintain this illusion; it's not coming from C. > Modern CPUs are tremendously sophisticated parallel processors that inspect adjacent instructions and try to run as many as possible in parallel, even speculatively executing instructions that may never run.  So what? These optimizations are done carefully so that the end result is the same as if the instructions ran one by one. You can't get away from this even if you write in assembly language. "Assembler is not a low-level language"

What you're really saying is that C is not keeping up with modern CPU architectures, and therefore it's not low level? I'd argue the opposite is the case: C is too low level, so compiler optimizers fill in *some* of the gaps to make it run well on modern CPUs. Then there's a slew of compiler- and CPU-specific tricks on top, which are truly low level, such as simd intrinsics. While these are not part of any C or C++ language standards, it's still possible to express them in C, even if it's just inlined assembly or some compiler attribute. If that isn't a low-level language, what is?

HABIB Laidouni

Research & Development Manager @ Decima Technologies 📍Privacian📍 ⚠️ Throughput Tactician ⚠️ Latency Alchemist ⚠️

1w

For history : In it's early days, C was referred to as a portable assembly language, and Dennis Ritchie (RIP 🎩 ) often laughed about it ... Thus said : C is a High level programming language (wait don't rush !) that is compiled into optimized (low level) assembly (or machine) code for execution ! The compiler translates the source code into a lower level representation, and then the linker (with respect to dependencies like Libraries, OS specs, etc. ...) combines these pieces into a final executable. Oversimplifications are often the beginning of misinterpretations, so be careful with theses terminologies !

Andrey Ptitsyn

Precision Health Sciences

1w

Yes, and a whale is not a fish, either. Four decades after the PDP-11 era, it's still true, but weird to see as a title. In the time of PDP-11, C was not considered a low-level language. All statements in this post were just as true back then. It is (now and then) a high-level language, but compact and flexible enough to allow optimizations for specific architecture. But only if you choose to do so.

John Simon

Software Engineer at Smartsheet

1w

There aren’t any hints to your application that execution will stop and move off to a different thread. C (and everything else) just assumes it’s the only program running on the system

Like
Reply
Leon Derczynski

LLM security at NVIDIA. Prof at ITU Copenhagen. Founder at garak.ai. ACL SIGSEC Chair.

1w

I LOVED this article so much. It's spot on. Chisnall absolutely nails it.

Like
Reply
Charles Manning

Consultant at Intependent consultant; The Yaffs guy

1w

I am not quite sure what you are trying to achieve here. Very few people would claim that C is the lowest level language. It is, however, one of the lowest level languages that is generally portable. The vast majority of computers are microcontrollers. You might think your laptop has "Intel Inside", but it also has dozens of microcontrollers. Even an SSD has two or more, then another in your WIFI module, Bluetooth module, power supply trackpad, keyboards,...

See more comments

To view or add a comment, sign in

Explore topics