Could C be implemented as a hybrid language? [duplicate] - c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Running/Interpreting C on top of the JVM?
By hybrid language I mean one that is compiled by a hybrid compiler (like Java). I understand it would be impracticable, because C is designed to be easily mapped to machine instructions, but I can't tell if there are any reasons why someone couldn't write a hybrid compiler for it.

Creating a custom virtual machine designed for running C would of course work, and work very well, with 1-1 mapping for many byte code instructions to real CPU instructions, and easy and fast JITing as a result too. Actually, LLVM for example is actually very much like this.
Doing C compiler targetting JVM would probably require making C heap to be a Java byte[] array, and pointers would be indexes to this array. Also C variables in stack might need to be done with simulated byte[] stack too, since it must be possible to get a pointer to them (compatible with heap pointer).
This is needed, because with direct Java refrences, it would be impossible to do pointer arithmetic and integer-pointer casts in C. One option to optimize this could be to make C char be 32 bits, which is allowed by C standard, but it would make that C implementation very awkward to use for processing for example text files, or anything really with byte data... Regardless, C compiled to Java bytecode would be very slow, as Java byte code can not do many C things "natively" with single byte code instructions.

C compilers exist for many architectures. Bytecode that Java uses probably can be simply viewed as just one more instruction set so why should not be possible? Probably pointers would not be a "real pointers" but some internal VM references.
Used to be a commercial compiler provided by axiomsol but all links to it appear dead (404) now.
Compiling C into Java code and then compiling Java is possible but many thinks seem really resolved in suboptimal way. With byte[], you even cannot read an integer in one go. C would probably benefit from its own virtual machine that would be simpler (as no garbage collector required). Or, at least, C must be compiled into bytecode directly. Who knows C well could look into the JamVM project that may provide an interesting start. It is a simple virtual machine to run Java bytecode.

Related

Low level languages and their dependencies

I am trying to understand exactly what it means that low-level languages are machine-dependent.
Let's take for example C, well if it is machine-dependent does it mean that if it was compiled on one computer it might not be able to run on another?
In the end processors executes machine code which is basicly a collection of binary numbers. The processor decode each binary number to figure out what it is supposed to do. One binary number could mean "Add register X to register Y and store the result in register Z". Another binary number could mean "Store the content of register X into the memory address held by register Y". And so on...
The complete description of these decoding rules (i.e. binary number into operation) represents the processors instruction set (aka ISA).
A low level language is a language where the code you can write maps very closely to the specific processors instruction set. Assembly is one obvious example. Since different processor may have different instruction sets, it's clear that an assembly program written for one processors ISA can't be used on a processor with a different ISA.
Let's take for example C, well if it is machine-dependent does it mean that if it was compiled on one computer it might not be able to run on another?
Correct. A program compiled for one processor (family) can't run on another processor with (completely) different ISA. The program needs to be recompiled.
Also notice that the target OS also plays a role. If you use the same processor but use different OS you'll also need to recompile.
There are at least 3 different kind of languages.
A languages that is so close to the target systems ISA that the source code can only be used on that specific target. Example: Assembly
A language that allows you to write code that can be used on many different targets using a target specific compilation. Example: C
A language that allows you to write code that can be used on many different targets without a target specific compilation. These still require some kind of target specific runtime environment to be installed. Example: Java.
High-Level languages are portable, meaning every architecture can run high-level programs but, compared to low-level programs (like written in Assembly or even machine code), they are less efficient and consume more memory.
Low-level programs are known as "closer to the hardware" and so they are optimized for a certain type of hardware architecture/processor, being faster programs, but relatively machine-dependant or not-very-portable.
So, a program compiled for a type of processor it's not valid for other types; it needs to be recompiled.
In the before
When the first processors came out, there was no programming language whatsoever, you had a very long and very complicated documentation with a list of "opcodes": the code you had to put into memory for a given operation to be executed in your processor. To create a program, you had to put a long string of number in memory, and hope everything worked as documented.
Later came Assembly languages. The point wasn't really to make algorithms easier to implement or to make the program readable by any human without any experience on the specific processor model you were working with, it was created to save you from spending days and days looking up things in a documentation. For this reason, there isn't "an assembly language" but thousands of them, one per instruction set (which, at the time, basically meant one per CPU model)
At this point in time, all languages were platform-dependent. If you decided to switch CPUs, you'd have to rewrite a significant portion (if not all) of your code. Recognizing that as a bit of a problem, someone created a the first platform-independent language (according to this SE question it was FORTRAN in 1954) that could be compiled to run on any CPU architecture as long as someone made a compiler for it.
Fast forward a bit and C was invented. C is a platform-independent programming language, in the sense that any C program (as long as it conforms with the standard) can be compiled to run on any CPU (as long as this CPU has a C compiler). Once a C program has been compiled, the resulting file is a platform-dependent binary and will only be able to run on the architecture it was compiled for.
C is platform-dependent
There's an issue though: a processor is more than just a list of opcodes. Most processors have hardware control devices like watchdogs or timers that can be completely different from one architecture to another, even the way to talk to other devices can change completely. As such, if you want to actually run a program on a CPU, you have to include things that make it platform-dependent.
A real life example of this is the Linux kernel. The majority of the kernel is written in C but there's still around 1% written in different kinds of assembly. This assembly is required to do things such as initialize the CPU or use timers. Using this hack means Linux can run on your desktop x86_64 CPU, your ARM Android phone or a RISCV SoC but adding any new architecture isn't as simple as just "compile it with your architecture's compiler".
So... Did I just say the only way to run a platform-independent on an actual processor is to use platform-dependent code? Yes, for most architectures, you have to.
Or is it?
But there's a catch! That's only true if you want to run you code on bare metal (meaning: without an OS). One of the great things of using an OS is how abstracted everything is: you don't need to know how the kernel initializes the CPU, nor do you need to know how it gets its clock, you just need to know how to access those abstracted resources.
But the way of accessing resources dependent on the OS, aren't we back to square one? We could be, if not for the standard library! This library is used to access functions like printf in a defined way. It doesn't matter if you're working on a Linux running on PowerPC or on an ARM Windows, printf will always print things on the standard output the same way.
If you write standard C using only the standard library (and intend for your program to run in an OS) C is completely platform-independent!
EDIT: As said in the comments below, even that is not enough. It doesn't really have anything to do with specific CPUs but some things such as the system function or the size of some types are documented as implementation-defined. To make C really platform independent you need to make sure to only use well defined functions of the STL and learn some best practice (never rely on sizeof(int)==4 for instance).
Thinking about 'what's a program' might help you understand your question. Is a program a collection of text (that you've typed in or otherwise manufactured) or is it something you run? Is it both?
In the case of a 'low-level' language like C I'd say that the text is the program source, and that this is turned into a program (aka executable) by a compiler. A program is something you can run. You need a C compiler for a system to be able to make the program source into a program for that system. Once built the program can only be run on systems close to the one it was compiled for. However there is a more interesting, if more difficult question: can you at least keep the program source the same, so that all you need to do is recompile? The answer to this is 'sort-of No' I sort-of think. For example you can't, in pure C, read the state of the shift key. Of course operating systems provide such facilities and you can interface to those in C, but then such code depends on the OS. There might be libraries (eg the curses library) that provide such facilities for many OS and that can help to reduce the dependency, but no library can clain to portably cover all OS.
In the case of a 'higher-level' language like python I'd say the text is both the program and the program source. There is no separate compilation stage with such languages, but you do need an interpreter on a system to be able to run your python program on that system. However that this is happening may not be clear to the user as you may well seem to be able to run your python 'program' just by naming it like you run your C programs. But this, most likely comes down to the shell (the part of the OS that deals with commands) knowing about python programs and invoking the interpreter for you. It can appear then that you can run your python program anywhere but in fact what you can do is pass the program to any python interpreter.
In the zoo of programming there are not only many, very varied beasts, but new kinds of beasts arise all the time, and old beasts metamorphose. Terms like 'program', 'script' and even 'executable' are often used loosely.

Why using Low-level-Languages or close to it ( C ) for embedded system and not a high level language, when all will be compiled to machine code?

I have searched but I couldn't find a clear answer. If we are compiling the code in a computer(powerful) then we are only sending a machine instruction to the memory in the embedded device. This, for my understandings, will make no difference if we use any sort of language because, in the end, we will be sending only a machine code to the embedded device, the code compilation which is the expensive phase is already done by a powerful machine!
Why using language like C ? Why not Java? we are sending a machine code at the end.
The answer partly lies in the runtime requirements and platform-provided expectations of a language: The size of the runtime for C is minimal - it needs a stack and that is about it to be able to start running code. For a compliant implementation static data initialisation is required, but you can run code without it - the initialisation itself could even be written in C, and even heap and standard library initialisation are optional, as is the presence of a library at all. It need have no OS dependencies, no interpreter and no virtual machine.
Most other languages require a great deal more runtime support and this is usually provided by an OS, runtime-library, or virtual machine. To operate "stand-alone" these languages would require that support to be "built-in" and would consequently be much larger - so much so that you may as well in many cases deploy a system with an OS and/or JVM for example in any case.
There are of course other reasons why particular languages are suited to embedded systems, such as hardware level access, performance and deterministic behaviour.
While the issue of a runtime environment and/or OS is a primary reason you do not often see higher-level languages in small embedded systems, it is by no means unheard of. The .Net Micro Framework for example allows C# to be used in embedded systems, and there are a number of embedded JVM implementations, and of course Linux distributions are widely embedded making language choice virtually unlimited. .Net Micro runs on a limited number of processor architectures, and requires a reasonably large memory (>256kb), and JVM implementations probably have similar requirements. Linux will not boot on less than about 16Mb ROM/4Mb RAM. Neither are particularly suited to hard real-time applications with deadlines in the microsecond domain.
C is more-or-less ubiquitous across 8, 16, 32 and 64 bit platforms and normally available for any architecture from day one, while support for other languages (other than perhaps C++ on 32 bit platforms at least) may be variable and patchy, and perhaps only available on more mature or widely used platforms.
From a developer point of view, one important consideration is also the availability of cross-compilation tools for the target platform and language. It is therefore a virtuous circle where developers choose C (or increasingly also C++) because that is the most widely available tool, and tool/chip vendors provide C and C++ tool-chains because that is what developers demand. Add to that the third-party support in the form of libraries, open-source code, debuggers, RTOS etc., and it would be a brave (or foolish) developer to select a language with barely any support. It is not just high level languages that suffer in this way. I once worked on a project programmed in Forth - a language even lower-level than C - it was a lonely experience, and while there were the enthusiastic advocates of the language, they were frankly a bit nuts favouring language evangelism over commercial success. C has in short reached critical mass acceptance and is hard to dislodge. C++ benefits from broad interoperability with C and similarly minimal runtime requirements, and by tool-chains that normally support both languages. So the only barrier to adoption of C++ is largely developer inertia, and to some extent availability on 8 and 16 bit platforms.
You're misunderstanding things a bit. Let's start by explaining the foundation of how computers work internally. I'll use simple and practical concepts here. For the underlying theories, read about Turing machines. So, what's your machine made up of? All computers have two basic components: a processor and a memory.
The memory is a sequential group of "cells" that works sort of like a table. If you "write" a value into the Nth cell, you can then retrieve that same value by "reading" from the Nth cell. This allows computers to "remember" things. If a computer is to perform a calculation, it needs to retrieve input data for it from somewhere, and to output data from it into somewhere. That place is the memory. In practice, the memory is what we call RAM, short for random access memory.
Then we have the processor. Its job is to perform the actual calculations on memory. The actual operations that are to be performed are mandated by a program, that is, a series of instructions that the processor is able to understand and execute. The processor decodes and executes an instruction, then the next one, and so on until the program halts (stops) the machine. If the program is add cell #1 and cell #2 and store result in cell #3, the processor will grab the values at cells 1 and 2, add their values together, and store the result into cell 3.
Now, there's some sort of an intrinsic question. Where is the program stored, if at all? First of all, a program can't be hardcoded into the wires. Otherwise, the system is not more of a computer than your microwave. To these problems are two distinct approaches/solutions: the Harvard architecture and the Von Neumann Architecture.
Basically, in the Harvard architecture, the data (as always has been) is stored in the memory. The code (or program) is stored somewhere else, usually in read-only memory. In the Von Neumann architecture, code is stored in memory, and is just another form of data. As a result, code is data, and data is code. It's worth noting that most modern systems use the Von Neumann architecture for several reasons, including the fact that this is the only way to implement just-in-time compilation, an essential part of runtime systems for modern bytecode-based programming languages, such as Java.
We now know what the machine does, and how it does that. However, how are both data and code stored? What's the "underlying format", and how shall it be interpreted? You've probably heard of this thing called the binary numeral system. In our usual decimal numeral system, we have ten digits, zero through nine. However, why exactly ten digits? Couldn't they be eight, or sixteen, or sixty, or even two? Be aware that it's impossible to create an unary based computational system.
Have you heard that computers are "logical and cold". Both of them are true... unless your machine has an AMD processor or a special kind of Pentium. The theory states that every logical predicate can be reduced to either "true" or "false". That is to say that "treu" and "false" are the basis of logic. Plus, computers are made up of electrical cruft, no? A light switch is either on or off, no? So, at the electrical level we can easily recognize two voltage levels, right? And we want to handle logic stuff, such as numbers, in computers, right? So zero and one may be, as the only feasible solution they are.
Now, taking all the theory into account, let's talk about programming languages and assembly languages. Assembly languages are a way to express binary instructions in a (supposedly) readable way to human programmers. For instance, something like this...
ADD 0, 1 # Add cells 0 and 1 together and store the result in cell 0
Could be translated by an assembler into something like...
110101110000000000000001
Both are equivalent, but humans will only understand the former, and processors will only understand the later.
A compiler is a program that translates input data that is expected to conform to the rules of a given programming language into another, usually lower-level form. For instance, a C compiler may take this code...
x = some_function(y + z);
And translate it into assembly code such as (of course this is not real assembly, BTW!)...
# Assume x is at cell 1, y at cell 2, and z at cell 3.
# Assuem that, when calling a function, the first argument
# is at cell 16, and the result is stored in cell 0.
MOVE 16, 2
ADD 16, 3
CALL some_function
MOVE 1, 0
And the assembler will spit (this is not random)...
11101001000100000000001001101110000100000000001110111011101101111010101111101111110110100111010010000000100000000
Now, let's talk about another language, namely Java. Java's compiler does not give you assembly/raw binary code, but bytecode. Bytecode is... like a generic, higher-level form of assembly language that the CPU can't understand (there are exceptions), but another program that directly runs on the CPU does. This means that the lie that some badly educated people spread around, that "both interpreted and compiled programs ultimately boil down to machine code" is false. If, for example, the interpreter is written in C, and has this line of code...
Bytecode some_bytecode;
/* ... */
execute_bytecode(&some_bytecode);
(Note: I won't translate that into assembly/binary again!) The processor executes the interpreter, and the interpreter's code executes the bytecode, by performing the actions specified by the bytecode. Although, if not optimized correctly, this can severely degrade performance, this is not the problem per se, but the fact that things such as reflection, garbage collection, and exceptions can add quite some overhead. For embedded systems, whose memories are small and whose processors are slow, this is something you want. You're wasting precious system resources on things you don't need. If C programs are slow on your Arduino, image a full blown Java/Python program with all sorts of bells and whistles! Even if you translated bytecode into machine code before inserting it into the system, support must be there for all that extra stuff, and results in basically the same unwanted overhead/waste. You would still need support for reflection, exceptions, garbage collection, etc... It's basically the same thing.
On most other environments, this is not a big deal, as memory is cheap and abundant, and processors are fast and powerful. Embedded systems have special needs, they're special by themselves, and things are not free in that land.
Why using language like C ? why not Java ? we are sending a machine
code at the end.
No, Java code does not compile to machine code, it needs a virtual machine (the JVM) on the target system.
You're partly right about the compilation, however, but still "higher-level" languages can result in less efficient machine code. For instance, the language can include garbage collection, run-time correctness checks, can't use all the "native" numeric types, etc.
In general it depends on the target. On small targets (i.e. microcontrollers like AVR) you don't have that complex programs running. Additionally, you need to access the hardware directly (f.e. a UART). High level languages like Java don't support accessing the hardware directly, so you usually end up with C.
In the case of C versus Java there's a major difference:
With C you compile the code and get a binary that runs on the target. It directly runs on the target.
Java instead creates Java Bytecode. The target CPU cannot process that. Instead it requires running another program: the Java runtime environment. That translates the Java Bytecode to actual machine code. Obviously this is more work and thus requires more processing power. While this isn't much of a concern for standard PCs it is for small embedded devices. (Note: some CPUs do actually have support for running Java bytecode directly. Those are exceptions though.)
Generally speaking, the compile step isn't the issue -- the limited resources and special requirements of the target device are.
you misunderstand something , 'compiling' java gives a different output then compiling a low level language , it is true that both are machine codes , but in c case the machine code is directly executable by the processor , whereas with java the output will be in an intermediate stage , a bytecode , and it can't be executed by the processor , it needs some extra work , a translation to a machine code , that is the only directly executable format , while that takes a extra time , c will be an attractive choice , because of its speed , with low level language you write you code then you compile to a target machine ( you need to specify the target to the compiler since each processor have his own machine code ) , then your code is understandable by the processor .
in the other hand c allows direct hardware access , that is not allowed in java-like languages even via an api
It's an industry thing.
There are three kinds of high level languages. Interpreted (lua, python, javascript), compiled to bytecode (java, c#), and compiled to machinne code (c, c++, fortran, cobol, pascal)
Yes, C is a high level language, and closer to java than to assembly.
High level languages are popular for two reasons.
Memory management, and a wide standard library.
Managed memory comes with a cost,
somebody must manage it. That's an issue not only for java and c#, where somebody must implement a VM, but also to baremetal c/c++ where someone must implement the memory allocation functions.
A wide standard library can't be supported by all targets because there aren't enough resources. ie, avr arduino doesn't support the full c++ standard library.
C gained popularity, because it can easily be converted to equivalent assembly code. Most statements can be converted, without optimization, to a bunch of fixed assembly instructions, so compilers are easy to program. And its standard is compact and easy to implement. C prevailed because it became the defacto standard for the lowest high level language of any arch.
So in the end, besides special snowflakes like cython, go, rust, haskell etc, industry decided that machinne code is compiled from C, C++ and most optimization efforts went that way
Languages, like java, decided to hide memory from the progarammer, so good luck trying to interface with low level stuff there. As by design they do that, almost nobody bothers trying to bring them to compete with C. Realistically, java without GC would be C++ with different syntax.
Finally, if all the industry money goes to one language, the cheapest/easyest thing to do is choosig that language.
You are right in that you can use any language that generates machine code. But JAVA is not one of them. JAVA, Python and even some languages that compile to machine code may have heavy system requirements. You could and some folks use Pascal, but C won the C vs Pascal war many years ago. There are some other languages that fell by the wayside that if you had a compiler for you could use. there are some new languages you can use, but the tools are not as mature and not as many targets as one would like. But it is very unlikely that they will unseat C. C is just the right amount of power/freedom, low enough and high enough.
Java is an interpreted language and (like all interpreted languages) produces an intermediate code that is not directly executable by the processor. So what you send to the embedded device would be the Bytecode and you should have a JVM running on it and interpreting your code. Clearly not feasible. For what concern the compiled languages (C, C++...) you are right to say that at the end you send machine code to the device. However consider that using high level features of a language will produce much more machine code that you would expect. If you use polymorphism for example, you have just a function call, but when you compile the machine code explodes. Consider also that very often the use of dynamic memory (malloc, new...) is not feasible on an embedded device.

Is assembly strictly required to make the "lowest" part of an operating system?

Im a mid-level(abstraction) programmer, and some months ago i started to think if i should reduce or increase abstraction(i've chosen to reduce).
Now, i think i've done most of the "research" about what i need, but still are a few questions remaining.
Right now while im "doing effectively nothing", im just reinforcing my C skills (bought "K&R C Programing Lang"), and im thinking to (after feel comfortable) start studying operating systems(like minix) just for learning purposes, but i have an idea stuck in my mind, and i don't really know if i should care.
In theory(i think, not sure), the higher level languages cannot refer to the hardware directly (like registers, memory locations, etc...) so the "perfect language" for the base would be assembly.
I already studied assembly(some time ago) just to see how it was (and i stopped in the middle of the book due to the outdated debugger that the book used(Assembly Language Step By Step, for Linux!)) but from what i have read, i din't liked the language a lot.
So the question is simple: Can an operating system(bootloader/kernel) be programmed without touching in a single line of assembly, and still be effective?
Even if it can, it will not be "cross-architecture", will it? (i386/arm/mips etc...)
Thanks for your support
You can do a significant amount of the work without assembly. Linux or NetBSD doesnt have to be completely re-written or patched for each of the many targets it runs on. Most of the code is portable and then there are abstraction layers and below the abstraction layer you find a target specific layer. Even within the target specific layers most of the code is not asm. I want to dispell this mistaken idea that in order to program registers or memory for a device driver for example that you need asm, you do not use asm for such things. You use asm for 1) instructions that a processor has that you cannot produce using a high level language. or 2) where high level language generated code is too slow.
For example in the ARM to enable or disable interrupts there is a specific instruction for accessing the processor state registers that you must use, so asm is required. but programming the interrupt controller is all done in the high level language. An example of the second point is you often find in C libraries that memcpy and other similar heavily used library functions are hand coded asm because it is dramatically faster.
Although you certainly CAN write and do anything you want in ASM, but you typically find that a high level language is used to access the "hardware directly (like registers, memory locations, etc...)". You should continue to re-inforce your C skills not just with the K&R book but also wander through the various C standards, you might find it disturbing how many "implementation defined" items there are, like bitfields, how variable sizes are promoted, etc. Just because a program you wrote 10 years ago keeps compiling and working using a/one specific brand of compiler (msvc, gcc, etc) doesnt mean the code is clean and portable and will keep working. Unfortunately gcc has taught many very bad programming habits that shock the user when the find out they didnt know the language a decade or so down the road and have to redo how they solve problems using that language.
You have answered your question yourself in "the higher level languages cannot refer to the hardware directly".
Whether you want it or not, at some point you will have to deal with assembly/machine code if you want to make an OS.
Interrupt and exception handlers will have to have some assembly code in them. So will need the scheduler (if not directly, indirectly). And the system call mechanism. And the bootloader.
What I've learned in the past reading websites and books is that:
a) many programmers dislikes assembly language because of the reasons we all know.
b) the main programming language for OS's seems to be C and even C++
c) assembly language can be used to 'speed up code' after profiling your source code in C or C++ (language doesn't matter in fact)
So, the combination of a mid level language and a low level language is in some cases inevitable. For example there is no use to speed up code for waiting on user input.
If it matters to build the shortest and fastest code for one specific range of computers (AMD, INTEL, ARM, DIGITAL-ALPHA, ...) then you should use assembler. My opinion...

Convert ASM to C (not reverse engineer)

I googled and I see a surprising amount of flippant responses basically laughing at the asker for asking such a question.
Microchip provides some source code for free (I don't want to post it here in case that's a no-no. Basically, google AN937, click the first link and there's a link for "source code" and its a zipped file). Its in ASM and when I look at it I start to go cross-eyed. I'd like to convert it to something resembling a c type language so that I can follow along. Because lines such as:
GLOBAL _24_bit_sub
movf BARGB2,w
subwf AARGB2,f
are probably very simple but they mean nothing to me.
There may be some automated ASM to C translator out there but all I can find are people saying its impossible. Frankly, its impossible for it to be impossible. Both languages have structure and that structure surely can be translated.
You can absolutely make a c program from assembler. The problem is it may not look like what you are thinking, or maybe it will. My PIC is rusty but using another assembler, say you had
add r1,r2
In C lets say that becomes
r1 = r1 + r2;
Possibly more readable. You lose any sense of variable names perhaps as values are jumping from memory to registers and back and the registers are being reused. If you are talking about the older pics that had what two registers an accumulator and another, well it actually might be easier because variables were in memory for the most part, you look at the address, something like
q = mem[0x12];
e = q;
q = mem[0x13];
e = e + q;
mem[0x12] = e;
Long and drawn out but it is clear that mem[0x12] = mem[0x12] + mem[0x13];
These memory locations are likely variables that will not jump around like compiled C code for a processor with a bunch of registers. The pic might make it easier to figure out the variables and then do a search and replace to name them across the file.
What you are looking for is called a static binary translation, not necessarily a translation from one binary to another (one processor to another) but in this case a translation from pic binary to C. Ideally you would want to take the assembler given in the app note and assemble it to a binary using the microchip tools, then do the translation. You can do dynamic binary translation as well but you are even less likely to find one of those and it doesnt normally result in C but one binary to another. Ever wonder how those $15 joysticks at wal-mart with pac-man and galaga work? The rom from the arcade was converted using static binary translation, optimized and cleaned up and the C or whatever intermediate language compiled for the new target processor in the handheld box. I imagine not all of them were done this way but am pretty sure some were.
The million dollar question, can you find a static binary translator for a pic? Who knows, you probably have to write one yourself. And guess what that means, you write a disassembler, and instead of disassembling to an instruction in the native assembler syntax like add r0,r1 you have your disassembler print out r0=r0+r1; By the time you finish this disassembler though you will know the pic assembly language so well that you wont need the asm to C translator. You have a chicken and egg problem.
Getting the exact same source code back from a compiled program is basically impossible. But decompilers have been an area of research in computer science (e.g. the dcc decompiler, which was a PhD project).
There are various algorithms that can be used to do pattern matching on assembly code and generate equivalent C code, but it is very hard to do this in a general way that works well for all inputs.
You might want to check out Boomerang for a semi-recent open source effort at a generalized decompiler.
I once worked a project where a significant part of the intellectual property was some serious algorithms coded up in x86 assembly code. To port the code to an embedded system, the developer of that code (not me) used a tool from an outfit called MicroAPL (if I recall correctly):
http://www.microapl.co.uk/asm2c/index.html
I was very, very surprised at how well the tool did.
On the other hand, I think it's one of those "if you have to ask, you can't afford it" type of things (their price ranges for a one-off conversion of a project work out to around 4 lines of assembly processed for a dollar).
But, often the assembly routines you get from a vendor are packaged as functions that can be called from C - so as long as the routines do what you want (on the processor you want to use), you might just need to assemble them and more or less forget about them - they're just library functions you call from C.
You can't deterministically convert assembly code to C. Interrupts, self modifying code, and other low level things have no representation other than inline assembly in C. There is only some extent to which an assembly to C process can work. Not to mention the resultant C code will probably be harder to understand than actually reading the assembly code... unless you are using this as a basis to begin reimplementation of the assembly code in C, then it is somewhat useful. Check out the Hex-Rays plugin for IDA.
Yes, it's very possible to reverse-engineer assembler code to good quality C.
I work for a MicroAPL, a company which produces a tool called Relogix to convert assembler code to C. It was mentioned in one of the other posts.
Please take a look at the examples on our web site:
http://www.microapl.co.uk/asm2c/index.html
There must be some automated ASM to C translator out there but all I can find are people saying its impossible. Frankly, its impossible for it to be impossible.
No, it's not. Compilation loses information: there is less information in the final object code than in the C source code. A decompiler cannot magically create that information from nothing, and so true decompilation is impossible.
It isn't impossible, just very hard. A skilled assembly and C programmer could probably do it, or you could look at using a Decompiler. Some of these do quite a good job of converting the asm to C, although you will probably have to rename some variables and methods.
Check out this site for a list of decompilers available for the x86 architecture.
Check out this: decompiler
A decompiler is the name given to a
computer program that performs the
reverse operation to that of a
compiler. That is, it translates a
file containing information at a
relatively low level of abstraction
(usually designed to be computer
readable rather than human readable)
into a form having a higher level of
abstraction (usually designed to be
human readable).
Not easily possible.
One of the great advantages of C over ASM apart from readability was that it prevented "clever" programing tricks.
There are numerous things you can do in assembler that have no direct C equivalent,
or involve tortuous syntax in C.
The other problem is datatypes most assemblers essentialy have only two interchangeable datatypes: bytes and words. There may be some language constructs to define ints and floats
etc. but there is no attempt to check that the memory is used as defined. So its very difficult to map ASM storage to C data types.
In addition all assembler storage is essentially a "struct"; storage is layed out in the order it is defined (unlike C where storage is ordered at the whim of the runtime). Many ASM programs depend on the exact storage layout - to acheive the same effect in C you would need to define all storage as part of a single struct.
Also there are a lot of absused instructions ( on olde worldy IBM manframes the LA, load address, instruction was regulary used to perform simple arithimatic as it was faster and didnt need an overflow register )
While it may be technically possible to translate to C the resulting C code would be less readable than the ASM code that was transalated.
I can say with 99% guarantee, there is no ready converter for this assembly language, so you need to write one. You can simply implement it replacing ASM command with C function:
movf BARGB2,w -> c_movf(BARGB2,w);
subwf AARGB2,f -> c_subwf(AARGB2,f);
This part is easy :)
Then you need to implement each function. You can declare registers as globals to make things easy. Also you can use not functions, but #defines, calling functions if needed. This will help with arguments/results processing.
#define c_subwf(x,y) // I don't know this ASM, but this is some Substraction must be here
Special case is ASM directives/labels, I think it can be converted with #defines only.
The fun starts when you'll reach some CPU-specific features. This can be simple function calls with stack operations, some specific IO/Memory operations. More fun are operations with Program Counter register, used for calculations, or using/counting ticks/latencies.
But there is another way, if this hardcore happens. It's hardcore too :)
There is a technique named dynamic recompilation exists. It's used in many emulators.
You don't need recompile your ASM, but the idea is almost the same. You can use all your #defines from first step, but add support of needed functionality to them (incrementing PC/Ticks). Also you need to add some virtual environment for your code, such as Memory/IO managers, etc.
Good luck :)
I think it is easier to pick up a book on PIC assembly and learn to read it. Assembler is generally quite simple to learn, as it is so low level.
Check out asm2c
Swift tool to transform DOS/PMODEW 386 TASM Assembly code to C code
It is difficult to convert a function from asm to C but doable by hand. Converting an entire program with a decompiler will give you code that can be impossible to understand since to much of the structure was lost during compilation. Without meaningful variable and function names the resultant C code is still very difficult to understand.
The output of a C compiler (especially unoptimised output) of an basic program could be translatable to C because of repeated patterns and structures.

Why is C so fast, and why aren't other languages as fast or faster? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
In listening to the Stack Overflow podcast, the jab keeps coming up that "real programmers" write in C, and that C is so much faster because it's "close to the machine." Leaving the former assertion for another post, what is special about C that allows it to be faster than other languages?
Or put another way: what's to stop other languages from being able to compile down to binary that runs every bit as fast as C?
There isn't much that's special about C. That's one of the reasons why it's fast.
Newer languages which have support for garbage collection, dynamic typing and other facilities which make it easier for the programmer to write programs.
The catch is, there is additional processing overhead which will degrade the performance of the application. C doesn't have any of that, which means that there is no overhead, but that means that the programmer needs to be able to allocate memory and free them to prevent memory leaks, and must deal with static typing of variables.
That said, many languages and platforms, such as Java (with its Java Virtual Machine) and .NET (with its Common Language Runtime) have improved performance over the years with advents such as just-in-time compilation which produces native machine code from bytecode to achieve higher performance.
There is a trade-off the C designers have made. That's to say, they made the decision to put speed above safety. C won't
Check array index bounds
Check for uninitialized variable values
Check for memory leaks
Check for null pointer dereference
When you index into an array, in Java it takes some method call in the virtual machine, bound checking and other sanity checks. That is valid and absolutely fine, because it adds safety where it's due. But in C, even pretty trivial things are not put in safety. For example, C doesn't require memcpy to check whether the regions to copy overlap. It's not designed as a language to program a big business application.
But these design decisions are not bugs in the C language. They are by design, as it allows compilers and library writers to get every bit of performance out of the computer. Here is the spirit of C how the C Rationale document explains it:
C code can be non-portable. Although it strove to give programmers the opportunity to write truly portable programs, the Committee did not want to force programmers into writing portably, to preclude the use of C as a ``high-level assembler'': the ability to write machine-specific code is one of the strengths of C.
Keep the spirit of C. The Committee kept as a major goal to preserve the traditional spirit of C. There are many facets of the spirit of C, but the essence is a community sentiment of the underlying principles upon which the C language is based. Some of the facets of the spirit of C can be summarized in phrases like
Trust the programmer.
Don't prevent the programmer from doing what needs to be done.
Keep the language small and simple.
Provide only one way to do an operation.
Make it fast, even if it is not guaranteed to be portable.
The last proverb needs a little explanation. The potential for efficient code generation is one of the most important strengths of C. To help ensure that no code explosion occurs for what appears to be a very simple operation, many operations are defined to be how the target machine's hardware does it rather than by a general abstract rule. An example of this willingness to live with what the machine does can be seen in the rules that govern the widening of char objects for use in expressions: whether the values of char objects widen to signed or unsigned quantities typically depends on which byte operation is more efficient on the target machine.
If you spend a month to build something in C that runs in 0.05 seconds, and I spend a day writing the same thing in Java, and it runs in 0.10 seconds, then is C really faster?
But to answer your question, well-written C code will generally run faster than well-written code in other languages because part of writing C code "well" includes doing manual optimizations at a near-machine level.
Although compilers are very clever indeed, they are not yet able to creatively come up with code that competes with hand-massaged algorithms (assuming the "hands" belong to a good C programmer).
Edit:
A lot of comments are along the lines of "I write in C and I don't think about optimizations."
But to take a specific example from this post:
In Delphi I could write this:
function RemoveAllAFromB(a, b: string): string;
var
before, after :string;
begin
Result := b;
if 0 < Pos(a,b) then begin
before := Copy(b,1,Pos(a,b)-Length(a));
after := Copy(b,Pos(a,b)+Length(a),Length(b));
Result := before + after;
Result := RemoveAllAFromB(a,Result); //recursive
end;
end;
and in C I write this:
char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
for (j = 0; j < len2; j++) {
if (s1[i] == s2[j]) {
break;
}
}
if (j == len2) { /* s1[i] is not found in s2 */
*result = s1[i];
result++; /* assuming your result array is long enough */
}
}
But how many optimizations are there in the C version? We make lots of decisions about implementation that I don't think about in the Delphi version. How is a string implemented? In Delphi I don't see it. In C, I've decided it will be a pointer to an array of ASCII integers, which we call chars. In C, we test for character existence one at a time. In Delphi, I use Pos.
And this is just a small example. In a large program, a C programmer has to make these kinds of low-level decisions with every few lines of code. It adds up to a hand-crafted, hand-optimized executable.
I didn't see it already, so I'll say it: C tends to be faster because almost everything else is written in C.
Java is built on C, Python is built on C (or Java, or .NET, etc.), Perl is, etc. The OS is written in C, the virtual machines are written in C, the compilers are written in C, the interpreters are written in C. Some things are still written in Assembly language, which tends to be even faster. More and more things are being written in something else, which is itself written in C.
Each statement that you write in other languages (not Assembly) is typically implemented underneath as several statements in C, which are compiled down to native machine code. Since those other languages tend to exist in order to obtain a higher level of abstraction than C, those extra statements required in C tend to be focused on adding safety, adding complexity, and providing error handling. Those are often good things, but they have a cost, and its names are speed and size.
Personally, I have written in literally dozens of languages spanning most of the available spectrum, and I personally have sought the magic that you hint at:
How can I have my cake and eat it, too? How can I play with high-level abstractions in my favorite language, then drop down to the nitty gritty of C for speed?
After a couple of years of research, my answer is Python (on C). You might want to give it a look. By the way, you can also drop down to Assembly from Python, too (with some minor help from a special library).
On the other hand, bad code can be written in any language. Therefore, C (or Assembly) code is not automatically faster. Likewise, some optimization tricks can bring portions of higher-level language code close to the performance level of raw C. But, for most applications, your program spends most of its time waiting on people or hardware, so the difference really does not matter.
Enjoy.
There are a lot of questions in there - mostly ones I am not qualified to answer. But for this last one:
what's to stop other languages from being able to compile down to binary that runs every bit as fast as C?
In a word, abstraction.
C is only one or two levels of abstraction away from machine language. Java and the .NET languages are at a minimum three levels of abstraction away from assembler. I'm not sure about Python and Ruby.
Typically, the more programmer toys (complex data types, etc.), the further you are from machine language and the more translation has to be done.
I'm off here and there, but that's the basic gist.
There are some good comments on this post with more details.
It is not so much that C is fast as that C's cost model is transparent. If a C program is slow, it is slow in an obvious way: by executing a lot of statements. Compared with the cost of operations in C, high-level operations on objects (especially reflection) or strings can have costs that are not obvious.
Two languages that generally compile to binaries which are just as fast as C are Standard ML (using the MLton compiler) and Objective Caml. If you check out the benchmarks game you'll find that for some benchmarks, like binary trees, the OCaml version is faster than C. (I didn't find any MLton entries.) But don't take the shootout too seriously; it is, as it says, a game, the the results often reflect how much effort people have put in tuning the code.
C is not always faster.
C is slower than, for example, Modern Fortran.
C is often slower than Java for some things (especially after the JIT compiler has had a go at your code).
C lets pointer aliasing happen, which means some good optimizations are not possible. Particularly when you have multiple execution units, this causes data fetch stalls. Ow.
The assumption that pointer arithmetic works really causes slow bloated performance on some CPU families (PIC particularly!) It used to suck the big one on segmented x86.
Basically, when you get a vector unit, or a parallelizing compiler, C stinks and modern Fortran runs faster.
C programmer tricks, like thunking (modifying the executable on the fly), cause CPU prefetch stalls.
Do you get the drift?
And our good friend, the x86, executes an instruction set that these days bears little relationship to the actual CPU architecture. Shadow registers, load-store optimizers, all in the CPU. So C is then close to the virtual metal. The real metal, Intel don't let you see. (Historically VLIW CPU's were a bit of a bust so, maybe that's no so bad.)
If you program in C on a high-performance DSP (maybe a TI DSP?), the compiler has to do some tricky stuff to unroll the C across the multiple parallel execution units. So in that case, C isn't close to the metal, but it is close to the compiler, which will do whole program optimization. Weird.
And finally, some CPUs (www.ajile.com) run Java bytecodes in hardware. C would a PITA to use on that CPU.
what's to stop other languages from
being able to compile down to binary
that runs every bit as fast as C?
Nothing. Modern languages like Java or .NET languages are oriented more toward programmer productivity rather than performance. Hardware is cheap nowadays. Also compilation to intermediate representation gives a lot of bonuses such as security, portability, etc. The .NET CLR can take advantage of different hardware. For example, you don't need to manually optimize/recompile program to use the SSE instructions set.
I guess you forgot that Assembly language is also a language :)
But seriously, C programs are faster only when the programmer knows what he's doing. You can easily write a C program that runs slower than programs written in other languages that do the same job.
The reason why C is faster is because it is designed in this way. It lets you do a lot of "lower level" stuff that helps the compiler to optimize the code. Or, shall we say, you the programmer are responsible for optimizing the code. But it's often quite tricky and error prone.
Other languages, like others already mentioned, focus more on productivity of the programmer. It is commonly believed that programmer time is much more expensive than machine time (even in the old days). So it makes a lot of sense to minimize the time programmers spend on writing and debugging programs instead of the running time of the programs. To do that, you will sacrifice a bit on what you can do to make the program faster because a lot of things are automated.
The main factors are that it's a statically-typed language and that's compiled to machine code. Also, since it's a low-level language, it generally doesn't do anything you don't tell it to.
These are some other factors that come to mind.
Variables are not automatically initialized
No bounds checking on arrays
Unchecked pointer manipulation
No integer overflow checking
Statically-typed variables
Function calls are static (unless you use function pointers)
Compiler writers have had lots of time to improve the optimizing code. Also, people program in C for the purpose of getting the best performance, so there's pressure to optimize the code.
Parts of the language specification are implementation-defined, so compilers are free to do things in the most optimal way
Most static-typed languages could be compiled just as fast or faster than C though, especially if they can make assumptions that C can't because of pointer aliasing, etc.
C++ is faster on average (as it was initially, largely a superset of C, though there are some differences). However, for specific benchmarks, there is often another language which is faster.
From The Computer Language Benchmarks Game:
fannjuch-redux was fastest in Scala
n-body and fasta were faster in Ada.
spectral-norm was fastest in Fortran.
reverse-complement, mandelbrot and pidigits were fastest in ATS.
regex-dna was fastest in JavaScript.
chameneou-redux was fastest is Java 7.
thread-ring was fastest in Haskell.
The rest of the benchmarks were fastest in C or C++.
For the most part, every C instruction corresponds to a very few assembler instructions. You are essentially writing higher level machine code, so you have control over almost everything the processor does. Many other compiled languages, such as C++, have a lot of simple looking instructions that can turn into much more code than you think it does (virtual functions, copy constructors, etc..) And interpreted languages like Java or Ruby have another layer of instructions that you never see - the Virtual Machine or Interpreter.
I know plenty of people have said it in a long winded way, but:
C is faster because it does less (for you).
Many of these answers give valid reasons for why C is, or is not, faster (either in general or in specific scenarios). It's undeniable that:
Many other languages provide automatic features that we take for granted. Bounds checking, run-time type checking, and automatic memory management, for example, don't come for free. There is at least some cost associated with these features, which we may not think about—or even realize—while writing code that uses these features.
The step from source to machine is often not as direct in other languages as it is in C.
OTOH, to say that compiled C code executes faster than other code written in other languages is a generalization that isn't always true. Counter-examples are easy to find (or contrive).
All of this notwithstanding, there is something else I have noticed that, I think, affects the comparative performance of C vs. many other languages more greatly than any other factor. To wit:
Other languages often make it easier to write code that executes more slowly. Often, it's even encouraged by the design philosophies of the language. Corollary: a C programmer is more likely to write code that doesn't perform unnecessary operations.
As an example, consider a simple Windows program in which a single main window is created. A C version would populate a WNDCLASS[EX] structure which would be passed to RegisterClass[Ex], then call CreateWindow[Ex] and enter a message loop. Highly simplified and abbreviated code follows:
WNDCLASS wc;
MSG msg;
wc.style = 0;
wc.lpfnWndProc = &WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWndCls";
RegisterClass(&wc);
CreateWindow("MainWndCls", "", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
An equivalent program in C# could be just one line of code:
Application.Run(new Form());
This one line of code provides all of the functionality that nearly 20 lines of C code did, and adds some things we left out, such as error checking. The richer, fuller library (compared to those used in a typical C project) did a lot of work for us, freeing our time to write many more snippets of code that look short to us but involve many steps behind the scenes.
But a rich library enabling easy and quick code bloat isn't really my point. My point is more apparent when you start examining what actually happens when our little one-liner actually executes. For fun sometime, enable .NET source access in Visual Studio 2008 or higher, and step into the simple one-linef above. One of the fun little gems you'll come across is this comment in the getter for Control.CreateParams:
// In a typical control this is accessed ten times to create and show a control.
// It is a net memory savings, then, to maintain a copy on control.
//
if (createParams == null) {
createParams = new CreateParams();
}
Ten times. The information roughly equivalent to the sum of what's stored in a WNDCLASSEX structure and what's passed to CreateWindowEx is retrieved from the Control class ten times before it's stored in a WNDCLASSEX structure and passed on to RegisterClassEx and CreateWindowEx.
All in all, the number of instructions executed to perform this very basic task is 2–3 orders of magnitude more in C# than in C. Part of this is due to the use of a feature-rich library, which is necessarily generalized, versus our simple C code which does exactly what we need and nothing more. But part of it is due to the fact that the modularized, object-oriented nature of .NET framework, lends itself to a lot of repetition of execution that often is avoided by a procedural approach.
I'm not trying to pick on C# or the .NET framework. Nor am I saying that modularization, generalization, library/language features, OOP, etc. are bad things. I used to do most of my development in C, later in C++, and most lately in C#. Similarly, before C, I used mostly assembly. And with each step "higher" my language goes, I write better, more maintainable, more robust programs in less time. They do, however, tend to execute a little more slowly.
I don't think anyone has mentioned the fact that much more effort has been put into C compilers than any other compiler, with perhaps the exception of Java.
C is extremely optimizable for many of the reasons already stated - more than almost any other language. So if the same amount of effort is put into other language compilers, C will probably still come out on top.
I think there is at least one candidate language that, with effort, could be optimized better than C and thus we could see implementations that produce faster binaries. I'm thinking of Digital Mars' D, because the creator took care to build a language that could potentially be better optimized than C. There may be other languages that have this possibility. However, I cannot imagine that any language will have compilers more than just a few percent faster than the best C compilers. I would love to be wrong.
I think the real "low hanging fruit" will be in languages that are designed to be easy for humans to optimize. A skilled programmer can make any language go faster, but sometimes you have to do ridiculous things or use unnatural constructs to make this happen. Although it will always take effort, a good language should produce relatively fast code without having to obsess over exactly how the program is written.
It's also important (at least to me) that the worst case code tends to be fast. There are numerous "proofs" on the web that Java is as fast or faster than C, but that is based on cherry picking examples.
I'm not big fan of C, but I know that anything I write in C is going to run well. With Java, it will "probably" run within 15% of the speed, usually within 25%, but in some cases it can be far worse. Any cases where it's just as fast or within a couple of percent are usually due to most of the time being spent in the library code which is heavily optimized C code anyway.
This is actually a bit of a perpetuated falsehood. While it is true that C programs are frequently faster, this is not always the case, especially if the C programmer isn't very good at it.
One big glaring hole that people tend to forget about is when the program has to block for some sort of I/O, such as user input in any GUI program. In these cases, it doesn't really matter what language you use since you are limited by the rate at which data can come in rather than how fast you can process it. In this case, it doesn't matter much if you are using C, Java, C# or even Perl; you just cannot go any faster than the data can come in.
The other major thing is that using garbage collection (GC) and not using proper pointers allows the virtual machine to make a number of optimizations not available in other languages. For instance, the JVM is capable of moving objects around on the heap to defragment it. This makes future allocations much faster since the next index can simply be used rather than looking it up in a table. Modern JVMs also don't have to actually deallocate memory; instead, they just move the live objects around when they GC and the spent memory from the dead objects is recovered essentially for free.
This also brings up an interesting point about C and even more so in C++. There is something of a design philosophy of "If you don't need it, you don't pay for it." The problem is that if you do want it, you end up paying through the nose for it. For instance, the vtable implementation in Java tends to be a lot better than C++ implementations, so virtual function calls are a lot faster. On the other hand, you have no choice but to use virtual functions in Java and they still cost something, but in programs that use a lot of virtual functions, the reduced cost adds up.
It's not so much about the language as the tools and libraries. The available libraries and compilers for C are much older than for newer languages. You might think this would make them slower, but au contraire.
These libraries were written at a time when processing power and memory were at a premium. They had to be written very efficiently in order to work at all. Developers of C compilers have also had a long time to work in all sorts of clever optimizations for different processors. C's maturity and wide adoption makes for a signficant advantage over other languages of the same age. It also gives C a speed advantage over newer tools that don't emphasize raw performance as much as C had to.
Amazing to see the old "C/C++ must be faster than Java because Java is interpreted" myth is still alive and kicking. There are articles going back a few years, as well as more recent ones, that explain with concepts or measurements why this simply isn't always the case.
Current virtual machine implementations (and not just the JVM, by the way) can take advantage of information gathered during program execution to dynamically tune the code as it runs, using a variety of techniques:
rendering frequent methods to machine code,
inlining small methods,
adjustment of locking
and a variety of other adjustments based on knowing what the code is actually doing, and on the actual characteristics of the environment in which it's running.
The lack of abstraction is what makes C faster. If you write an output statement you know exactly what is happening. If you write an output statement in Java it is getting compiled to a class file which then gets run on a virtual machine, introducing a layer of abstraction.
The lack of object-oriented features as a part of the language also increases its speed do to less code being generated. If you use C as an object-oriented language, then you are doing all the coding for things such as classes, inheritance, etc. This means rather than make something generalized enough for everyone with the amount of code and the performance penalty that requires you only write what you need to get the job done.
The fastest running code would be carefully handcrafted machine code. Assembler will be almost as good. Both are very low level and it takes a lot of writing code to do things. C is a little above assembler. You still have the ability to control things at a very low level in the actual machine, but there is enough abstraction, make writing it faster and easier then assembler.
Other languages, such as C# and Java, are even more abstract. While Assembler and machine code are called low-level languages, C# and JAVA (and many others) are called high-level languages. C is sometimes called a midlevel language.
Don't take someone’s word for it; look at the disassembly for both C and your language-of-choice in any performance critical part of your code. I think you can just look in the disassembly window at runtime in Visual Studio to see disassembled .NET code. It should be possible, if tricky, for Java using WinDbg, though if you do it with .NET, many of the issues would be the same.
I don't like to write in C if I don't need to, but I think many of the claims made in these answers that tout the speed of languages other than C can be put aside by simply disassembling the same routine in C and in your higher level language of choice, especially if lots of data is involved as is common in performance critical applications. Fortran may be an exception in its area of expertise; I don't know. Is it higher level than C?
The first time I did compare JITed code with native code resolved any and all questions whether .NET code could run comparably to C code. The extra level of abstraction and all the safety checks come with a significant cost. The same costs would probably apply to Java, but don't take my word for it; try it on something where performance is critical. (Does anyone know enough about JITed Java to locate a compiled procedure in memory? It should certainly be possible.)
Setting aside advanced optimization techniques such as hot-spot optimization, pre-compiled meta-algorithms, and various forms of parallelism, the fundamental speed of a language correlates strongly with the implicit behind-the-scenes complexity required to support the operations that would commonly be specified within inner loops.
Perhaps the most obvious is validity checking on indirect memory references—such as checking pointers for null and checking indexes against array boundaries. Most high-level languages perform these checks implicitly, but C does not. However, this is not necessarily a fundamental limitation of these other languages—a sufficiently clever compiler may be capable of removing these checks from the inner loops of an algorithm through some form of loop-invariant code motion.
The more fundamental advantage of C (and to a similar extent the closely related C++) is a heavy reliance on stack-based memory allocation, which is inherently fast for allocation, deallocation, and access. In C (and C++) the primary call stack can be used for allocation of primitives, arrays, and aggregates (struct/class).
While C does offer the capability to dynamically allocate memory of arbitrary size and lifetime (using the so called 'heap'), doing so is avoided by default (the stack is used instead).
Tantalizingly, it is sometimes possible to replicate the C memory allocation strategy within the runtime environments of other programming languages. This has been demonstrated by asm.js, which allows code written in C or C++ to be translated into a subset of JavaScript and run safely in a web browser environment—with near-native speed.
As somewhat of an aside, another area where C and C++ outshine most other languages for speed is the ability to seamlessly integrate with native machine instruction sets. A notable example of this is the (compiler and platform dependent) availability of SIMD intrinsics which support the construction of custom algorithms that take advantage of the now nearly ubiquitous parallel processing hardware—while still utilizing the data allocation abstractions provided by the language (lower-level register allocation is managed by the compiler).
1) As others have said, C does less for you. No initializing variables, no array bounds checking, no memory management, etc. Those features in other languages cost memory and CPU cycles that C doesn't spend.
2) Answers saying that C is less abstracted and therefore faster are only half correct I think. Technically speaking, if you had a "sufficiently advanced compiler" for language X, then language X could approach or equal the speed of C. The difference with C is that since it maps so obviously (if you've taken an architecture course) and directly to assembly language that even a naive compiler can do a decent job. For something like Python, you need a very advanced compiler to predict the probable types of objects and generate machine code on the fly -- C's semantics are simple enough that a simple compiler can do well.
Back in the good ole days, there were just two types of languages: compiled and interpreted.
Compiled languages utilized a "compiler" to read the language syntax and convert it into identical assembly language code, which could than just directly on the CPU. Interpreted languages used a couple of different schemes, but essentially the language syntax was converted into an intermediate form, and then run in a "interpreter", an environment for executing the code.
Thus, in a sense, there was another "layer" -- the interpreter -- between the code and the machine. And, as always the case in a computer, more means more resources get used. Interpreters were slower, because they had to perform more operations.
More recently, we've seen more hybrid languages like Java, that employ both a compiler and an interpreter to make them work. It's complicated, but a JVM is faster, more sophisticated and way more optimized than the old interpreters, so it stands a much better change of performing (over time) closer to just straight compiled code. Of course, the newer compilers also have more fancy optimizing tricks so they tend to generate way better code than they used to as well. But most optimizations, most often (although not always) make some type of trade-off such that they are not always faster in all circumstances. Like everything else, nothing comes for free, so the optimizers must get their boast from somewhere (although often times it using compile-time CPU to save runtime CPU).
Getting back to C, it is a simple language, that can be compiled into fairly optimized assembly and then run directly on the target machine. In C, if you increment an integer, it's more than likely that it is only one assembler step in the CPU, in Java however, it could end up being a lot more than that (and could include a bit of garbage collection as well :-) C offers you an abstraction that is way closer to the machine (assembler is the closest), but you end up having to do way more work to get it going and it is not as protected, easy to use or error friendly. Most other languages give you a higher abstraction and take care of more of the underlying details for you, but in exchange for their advanced functionality they require more resources to run. As you generalize some solutions, you have to handle a broader range of computing, which often requires more resources.
I have found an answer on a link about why some languages are faster and some are slower, I hope this will clear more about why C or C++ is faster than others, There are some other languages also that is faster than C, but we can not use all of them. Some explanation -
One of the big reasons that Fortran remains important is because it's fast: number crunching routines written in Fortran tend to be quicker than equivalent routines written in most other languages. The languages that are competing with Fortran in this space—C and C++—are used because they're competitive with this performance.
This raises the question: why? What is it about C++ and Fortran that make them fast, and why do they outperform other popular languages, such as Java or Python?
Interpreting versus compiling
There are many ways to categorize and define programming languages, according to the style of programming they encourage and features they offer. When looking at performance, the biggest single distinction is between interpreted languages and compiled ones.
The divide is not hard; rather, there's a spectrum. At one end, we have traditional compiled languages, a group that includes Fortran, C, and C++. In these languages, there is a discrete compilation stage that translates the source code of a program into an executable form that the processor can use.
This compilation process has several steps. The source code is analyzed and parsed. Basic coding mistakes such as typos and spelling errors can be detected at this point. The parsed code is used to generate an in-memory representation, which too can be used to detect mistakes—this time, semantic mistakes, such as calling functions that don't exist, or trying to perform arithmetic operations on strings of text.
This in-memory representation is then used to drive a code generator, the part that produces executable code. Code optimization, to improve the performance of the generated code, is performed at various times within this process: high-level optimizations can be performed on the code representation, and lower-level optimizations are used on the output of the code generator.
Actually executing the code happens later. The entire compilation process is simply used to create something that can be executed.
At the opposite end, we have interpreters. The interpreters will include a parsing stage similar to that of the compiler, but this is then used to drive direct execution, with the program being run immediately.
The simplest interpreter has within it executable code corresponding to the various features the language supports—so it will have functions for adding numbers, joining strings, whatever else a given language has. As it parses the code, it will look up the corresponding function and execute it. Variables created in the program will be kept in some kind of lookup table that maps their names to their data.
The most extreme example of the interpreter style is something like a batch file or shell script. In these languages, the executable code is often not even built into the interpreter itself, but rather separate, standalone programs.
So why does this make a difference to performance? In general, each layer of indirection reduces performance. For example, the fastest way to add two numbers is to have both of those numbers in registers in the processor, and to use the processor's add instruction. That's what compiled programs can do; they can put variables into registers and take advantage of processor instructions. But in interpreted programs, that same addition might require two lookups in a table of variables to fetch the values to add, then calling a function to perform the addition. That function may very well use the same processor instruction as the compiled program uses to perform the actual addition, but all the extra work before the instruction can actually be used makes things slower.
If you want to know more please check the source.
Some C++ algorithms are faster than C, and some implementations of algorithms or design patterns in other languages can be faster than C.
When people say that C is fast, and then move on to talking about some other language, they are generally using C's performance as a benchmark.
Just step through the machine code in your IDE, and you'll see why it's faster (if it's faster). It leaves out a lot of hand-holding. Chances are your Cxx can also be told to leave it out too, in which case it should be about the same.
Compiler optimizations are overrated, as are almost all perceptions about language speed.
Optimization of generated code only makes a difference in hotspot code, that is, tight algorithms devoid of function calls (explicit or implicit). Anywhere else, it achieves very little.
With modern optimizing compilers, it's highly unlikely that a pure C program is going to be all that much faster than compiled .NET code, if at all. With the productivity enhancement that frameworks like .NET provide the developer, you can do things in a day that used to take weeks or months in regular C. Coupled with the cheap cost of hardware compared to a developer's salary, it's just way cheaper to write the stuff in a high-level language and throw hardware at any slowness.
The reason Jeff and Joel talk about C being the "real programmer" language is because there isn't any hand-holding in C. You must allocate your own memory, deallocate that memory, do your own bounds-checking, etc. There isn't any such thing as new object(); There isn't any garbage collection, classes, OOP, entity frameworks, LINQ, properties, attributes, fields, or anything like that.
You have to know things like pointer arithmetic and how to dereference a pointer. And, for that matter, know and understand what a pointer is. You have to know what a stack frame is and what the instruction pointer is. You have to know the memory model of the CPU architecture you're working on. There is a lot of implicit understanding of the architecture of a microcomputer (usually the microcomputer you're working on) when programming in C that simply is not present nor necessary when programming in something like C# or Java. All of that information has been off-loaded to the compiler (or VM) programmer.
It's the difference between automatic and manual. Higher-level languages are abstractions, thus automated. C/C++ are manually controlled and handled; even error checking code is sometimes a manual labor.
C and C++ are also compiled languages which means none of that run-everywhere business. These languages have to be fine-tuned for the hardware you work with, thus adding an extra layer of gotcha. Though this is slightly phasing out now as C/C++ compilers are becoming more common across all platforms. You can do cross compilations between platforms. It's still not a run everywhere situation, and you’re basically instructing compiler A to compile against compiler B the same code on a different architecture.
Bottom line, C languages are not meant to be easy to understand or reason. This is also why they’re referred to as systems languages. They came out before all this high-level abstraction nonsense. This is also why they are not used for front end web programming. They’re just not suited to the task; they’re meant to solve complex problems that can't be resolved with conventional language tooling.
This is why you get crazy stuff, like micro-architectures, drivers, quantum physics, AAA games, and operating systems. There are things C and C++ are just well suited for. Speed and number crunching being the chief areas.
C is fast because it is natively compiled, low-level language. But C is not the fastest. The Recursive Fibonacci Benchmark shows that Rust, Crystal, and Nim can be faster.

Resources