Related
I am currently playing around with programming languages. I have spent some time writing parsers and interpreters in high level languages (most notably Haxe).
I have had some results, that I think are actually quite nice, but now I'd like to make them fast.
My idea was to translate the input language into C.
My C knowledge is limitted to what you learn at university. Beyond some exercises, I have never written actual C programs. But I feel confident I can make it work.
Of course I could try to write a frontend for the LLVM or to generate MSIL or JVM bytecode. But I feel that's too much to learn right now, and I don't see much of a gain actually.
Also C is perfectly human readable, so if I screw up, it's much easier to understand why. And C is, after all, high level. I can really translate concepts from the input language without too much mind-bending. I should be having something working up and running in a reasonable amount of time and then optimize it as I see fit.
So: Are there any downsides to using C? Can you recommend an alternative?
Thank you for your insight :)
Edit: Some Clarification
The reason why I want to go all the way down is, that I am writing a language with OOP support and I want to actually implement my method dispatching by hand, because I have something very specific in mind.
A primary area of use would be writing HTTP services, but I could image adding bindings to a GUI library (wxWidgets maybe) or whatever.
C is a good and quite popular choice for what you're trying to do.
Still, take a look at LLVM's intermediate language (IR). It's pretty readable and I think it's cleaner and easier to generate and parse than C. LLVM comes with quite a big collection of tools to work with it. You can generate native code for variety of platforms (as with C but with slightly more control over output) or for virtual machines. Possibility of JIT compilation is also a plus.
See The Architecture of Open Source Applications, Chapter 11 for introduction to LLVM approach and some snippets of IR.
What is your target environment? This might help us give you better answer.
C is actually a pretty good choice for a target language for a little or experimental compiler -- its widely available on many platforms, so your compiler becomes immediately useful in many environments. The main drawback is dealing with things that are not well supported in C, or are not well defined in the C spec. For example, if you want to do dynamic code generation (JIT compilation), C is problematic. Things like stack unwinding and reflection are tricky to do in C (though setjmp/longjmp and careful use of structs for which you generate layout descriptions can do a lot). Things like word sizes, big or little-endian layout, and arithmetic precision vary between C compilers, so you have to be aware of that, but those are things you need to deal with if you want to support multiple target machines anyways.
Other languages can be used as well -- the main advantage of C is its ubiquity.
You might consider C--, a C-like language intended to be a better target for code generation than C.
C is a good choice, IMHO. Unlike many languages, C is generally considered "elegant" in that you have only 32 keywords, and very basic constructs (sequence, selection, iteration), with a very simple-and-consistent collection of tokens and operators.
Because syntax is very consistent within C (brackets and braces, blocks and statements, use of expressions), you're not marching into an unbounded world of language expansion. C is a mature language, has weathered time nicely, and now-a-days is a "known quantity" (which is really hard to say about many other languages, even "mature" ones).
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 12 years ago.
In programming language discussions we hear terms such as low-level, middle-level, and high-level. How are these determined? Would C be considered a middle-level language?
Low-, high-, blah-level is all just vague terminology with no deterministic factor behind it. Traditionally, low-level languages refer to machine code and assembly, and high-level refers to everything else. More recently, we have "very high level" used for scripting languages (anything interpreted rather than compiled). I have never heard "middle" used for anything.
That said, you will hear lots of argument on whether C or C++ are low-level or high-level languages, as some people prefer to think of C/C++ as low-level now given their relative position to other languages (25 years ago this would be unheard of). It is largely meaningless unless you agree on a definition of low-level or high-level. So you could easily come up with a definition of "middle-level" and then use that to determine whether C counts as middle-level or not.
I found this to be the reason for such a bias between high level and low level classification.
C is often called a middle-level
computer language as it is a
combination of the elements of
high-level languages with the
functionalism of assembly language.
High Level language :
A high-level programming language is
one that's more user-friendly, to some
extent platform-independent, and
abstract from low-level computer
processor operations such as memory
accesses.
Low Level Language :
A low-level programming language is a
one that is more machine specific, and
from computer processor operations
such as memory accesses is directly
dependent.
courtesy : http://www.cfanatic.com/showthread.php?s=cfa39a622e72217cce1fb9118a90fd79&t=130
If you look at it from a function point perspective, it would be middle to low level.
http://www.qsm.com/resources/function-point-languages-table/index.html
Though the terminology is quite vague, I consider C to be a mid-to-low-level language. You have very low-level features (manual memory access, pointer arithmetics) and very few abstractions - It's almost literally converted to assembly. As Wikipedia states C++ is a typical mid-level language, since you have the low-level access of C combined with abstractions like object orientation, templates and even some functional programming.
Middle-level language is used because you can go really low, doing assembly, but it also contains elements or abstractions of higher-level languages
but i agree with danben..there's no deterministic factor behind it...
My old C books from before C++ was around talk about C as a middle-level language. But that was before Java, .NET, Ruby, Python, etc were around. I'd say the (vague) boundaries have shifted somewhat as the high-level languages like Ruby/Python became so much more advanced.
C is only one step above Assembly, but above C you have C++, then Java/.net, then Ruby/Python. So I'd say C is now a lower or lower-mid level language since you can quite easily map it to asm/machine code. I'd say C++ is a mid-level language, Java/C# mid-high, Ruby/Python high.
C is often called portable assembly by people who can program in assembly. Now, ask the same group of people if C is too much or too little abstraction away from assembly and you'll see rotten fruit start to fly (well, perhaps good fruit too, depending on what's available).
The 'level' to which you refer is simply the amount of abstraction between you and a compiled heap of ones and zeros. Some may say math is nicely abstracted in C while strings are just wretched to deal with.
In essence, it really depends on what you are using C to do. I don't feel that it can be classified as a whole.
I think C should still be classed as a high level language. Compared to assembly it really is high level.
It has loops for one which makes a huge difference rather than trying to roll your own with jump statements.
Try writing assembly on an 8 bit microcontroller and then jump to using C. You'll soon realise just how far apart they are.
Edit: Since when has there been such a thing as a mid level language anyway? Mid level compared to what?
From the usage point of view, in contrast to C++, C provides less language syntax, semantics and facilities. C is a lower level language than C++.
while from function point of view, if a language can provide powerful functions under the help of remarkable infrastructure, such as Windows SDK C API, I think it really can be called a "high level" language.
Scripting languages provide another usage of programming language: interpreted rather than compiled. While its function is somewhat limited.
therefore, you need it, you use it. the better achieved, the higher level you enjoyed!
C is a high-level language in the sense that there's very little one-to-one correspondence between a line of C code and the equivalent machine code. Compared to languages like C++ or Java, C provides very few abstractions; beyond byte streams, arrays, and pointers (which, yes, are abstractions), there isn't a whole lot in the C toolkit.
It seems like languages are divided by generation.
These generations are widely considered to be (with the definitions having greater variance the higher you get):
Machine Languages.
Assembly languages (which is just a human readable version of Machine Languages)
Structured languages (FORTRAN, COBOL, C, C++, C#, Java, Python, etc...)
Languages used to build applications in a specific area (PL/SQL, R, FoxPro, etc...)
Languages that work within specific constraints rather than algorithms. These are usually used in AI. (Prolog, etc...)
Having said all that, the fourth generation is sometimes said to include object-oriented languages.
I'll answer with another question: is C++ a high-level language?
It isn't: The language itself gives you classes, operator overloading, and templates. That's just syntactic sugar around structs, functions, and macros. As an example, Lightblue BREW is a zero-overhead bridge between BREW (object-oriented C) and C++ because BREW happens to be binary-compatible with C++!
Cfront was the original "compiler" for C++: it preprocessed it into C. The original compilers for Objective-C was also just preprocessors.
It is: You can write code which uses "high-level" features (memory management, garbage collection, lambda expressions, ...) without worrying about "low level" details (forgetting to free). There are plenty of C++ libraries out there (e.g. Boost).
It's far more useful to classify a language by the features it has instead of giving it a high-level-ness number. Take, for example, unpacking a .bmp ("DIB") header:
C: Easy. Just use a struct. You might have to worry about endianness, packing, and portability to odd architectures.
C++: Use a struct. If you're clever, the structs can also handle endianness and packing in a mostly portable way.
Java: You have to calculate offsets into the header. If it's a byte array, you have to do masking and bitshifting yourself. (If it's a nio buffer, you just set the endianness.)
REALbasic: It's a MemoryBlock. You have to calculate offsets into the header yourself. You might have to worry about endianness, depending on whether you use a MemoryBlock extension plugin.
Python: Just import struct. None of the fields have names though, so you have to keep track of what order they're in, so it's marginally bette than calculating offsets.
There, an easy problem where C++ seems to be the highest-level language and C comes second.
I'll also note that the existence of "low level" features does not make a language low-level. In C#, you can write "unmanaged" code and use pointer arithmetic. In Python, you can import ctypes to call C or C++ functions and import objc to call Objective-C, losing all type-safety (I do this when I'd otherwise write a quick test program, because it's much easier than repeated compiling and running).
Besides, pointer arithmetic need not be low-level. Pointers are usually implemented as memory addresses, and C++ references are usually implemented as pointers, but there's no reason why you can't change the underlying implementation to make pointers bounds-checked, or even type-checked.
I think it is up to the user how he is using it.A high level language is that which provide abstraction and low level language is that which uses resources provided by OS(System call).In that way if a programmer is using system call to perform some task then c is a low level programming language,and if the same programmer use bash commands or other function which give view of programming then c is a high level language.So C is both high and low level programming language .
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
It seems to be a mainstream opinion that assembly programming takes longer and is more difficult to program in than a higher level language such as C. Therefore it seems to be recommend or assumed that it is better to write in a higher level language for these reasons and for the reason of better portability.
Recently I've been writing in x86 assembly and it has dawned on me that perhaps these reasons are not really true, except perhaps portability. Perhaps it is more of a matter of familiarity and knowing how to write assembly well. I also noticed that programming in assembly is quite different than programming in an HLL. Perhaps a good and experienced assembly programmer could write programs just as easily and as quickly as an experienced C programmer writing in C.
Perhaps it is because assembly programming is quite different than HLLs, and so requires different thinking, methods and ways, which makes it seem very awkward to program in for the unfamiliar, and so gives it its bad name for writing programs in.
If portability isn't an issue, then really, what would C have over a good assembler such as NASM?
Edit:
Just to point out. When you are writing in assembly, you don't have to write just in instruction codes. You can use macros and procedures and your own conventions to make various abstractions to make programs more modular, more maintainable and easier to read. This is where being familiar with how to write good assembly comes in.
Hellо, I am a compiler.
I just scanned thousands of lines of code while you were reading this sentence. I browsed through millions of possibilities of optimizing a single line of yours using hundreds of different optimization techniques based on a vast amount of academic research that you would spend years getting at. I won't feel any embarrassment, not even a slight ick, when I convert a three-line loop to thousands of instructions just to make it faster. I have no shame to go to great lengths of optimization or to do the dirtiest tricks. And if you don't want me to, maybe for a day or two, I'll behave and do it the way you like. I can transform the methods I'm using whenever you want, without even changing a single line of your code. I can even show you how your code would look in assembly, on different processor architectures and different operating systems and in different assembly conventions if you'd like. Yes, all in seconds. Because, you know, I can; and you know, you can't.
P.S. Oh, by the way you weren't using half of the code you wrote. I did you a favor and threw it away.
ASM has poor legibility and isn't really maintainable compared to higher-level languages.
Also, there are many fewer ASM developers than for other more popular languages, such as C.
Furthermore, if you use a higher-level language and new ASM instructions become available (SSE for example), you just need to update your compiler and your old code can easily make use of the new instructions.
What if the next CPU has twice as many registers?
The converse of this question would be: What functionality do compilers provide?
I doubt you can/want to/should optimize your ASM better than gcc -O3 can.
I've written shedloads of assembler for the 6502, Z80, 6809 and 8086 chips. I stopped doing so as soon as C compilers became available for the platforms I was addressing, and immediately became at least 10x more productive. Most good programmers use the tools they use for rational reasons.
I love programming in assembly language, but it takes more code to do the same thing as in a high-level languge, and there is a direct correlation between lines of code and bugs. (This was explained decades ago in The Mythical Man-Month.)
It's possible to think of C as 'high level assembly', but get a few steps above that and you're in a different world. In C# you don't think twice about writing this:
foreach (string s in listOfStrings) { /* do stuff */ }
This would be dozens, maybe hundreds of lines of code in assembly, each programmer implementing it would take a different approach, and the next person coming along would have to figure it out. So if you believe (as many do) that programs are written primarily for other people to read, assembly is less readable than the typical HLL.
Edit: I accumulated a personal library of code used for common tasks, and macros for implementing C-like control structures. But I hit the wall in the 90s, when GUIs became the norm. Too much time was being spent on things that were routine.
The last task I had where ASM was essential was a few years ago, writing code to combat malware. No user interface, so it was all the fun parts without the bloat.
In addition to other people's answers of readability, maintainability, shorter code and therefore fewer bugs, and being much easier, I'll add an additional reason:
program speed.
Yes, in assembly you can hand tune your code to make use of every last cycle and make it as fast as is physically possible. However who has the time? If you write a not-completely-stupid C program, the compiler will do a really good job of optimizing for you. Probably making at least 95% of the optimizations you'd do by hand, without you having to worry about keeping track of any of it. There's definitely a 90/10 kind of rule here, where that last 5% of optimizations will end up taking up 95% of your time. So why bother?
If an average production program has say 100k lines of code, and each line is about 8-12 assembler instructions, that would be 1 million of assembler instructions.
Even if you could write all this by hand at a decent speed (remember, its 8 times more code that you have to write), what happens if you want to change some of the functionality? Understanding something you wrote a few weeks ago out of those 1 million instructions is a nightmare! There's no modules, no classes, no object-oriented design, no frameworks, no nothing. And the amount of similar looking code you have to write for even the simplest things is daunting at best.
Besides, you can't optimize your code nearly as well as a high level language. Where C for example performs an insane number of optimizations because you describe your intent, not only your code, in assembler you only write code, the assembler can't really perform any note-worthy optimizations on your code. What you write is what you get, and trust me, you can't reliably optimize 1 million instructions that you patch and patch as you write it.
Well I have been writing a lot of assembly "in the old days", and I can assure you that I am much more productive when I write programs in a high level language.
A reasonable level of assembler competence is a useful skill, especially if you work at any sort of system level or embedded programming, not so much because you have to write that much assembler, but because sometimes it's important to understand what the box is really doing. If you don't have a low-level understanding of assembler concepts and issues, this can be very difficult.
However, as for actually writing much code in assembler, there are several reasons it's not much done.
There's simply no (almost) need. Except for something like the very early system initialization and perhaps a few assembler fragments hidden in C functions or macros, all very low-level code that might once have been written in assembler can be written in C or C++ with no difficulty.
Code in higher-level languages (even C and C++) condenses functionality into far fewer lines, and there is considerable research showing that the number of bugs correlates with the number of lines of source code. Ie, the same problem, solved in assembler and C, will have more bugs in assembler simply because its longer. The same argument motivates the move to higher level languages such as Perl, Python, etc.
Writing in assembler, you have to deal with every single aspect of the problem, from detailed memory layout, instruction selection, algorithm choices, stack management, etc. Higher level languages take all this away from you, which is why are so much denser in terms of LOC.
Essentially, all of the above are related to the level of abstraction available to you in assembler versus C or some other language. Assembler forces you to make all of your own abstractions, and to maintain them through your own self-discipline, where any mid-level language like C, and especially higher level languages, provide you with abstractions out of the box, as well as the ability to create new ones relatively easily.
As a developer who spends most of his time in the embedded programming world, I would argue that assembly is far from a dead/obsolete language. There is a certain close-to-the-metal level of coding (for example, in drivers) that sometimes cannot be expressed as accurately or efficiently in a higher-level language. We write nearly all of our hardware interface routines in assembler.
That being said, this assembly code is wrapped such that it can be called from C code and is treated like a library. We don't write the entire program in assembly for many reasons. First and foremost is portability; our code base is used on several products that use different architectures and we want to maximize the amount of code that can be shared between them. Second is developer familiarity. Simply put, schools don't teach assembly like they used to, and our developers are far more productive in C than in assembly. Also, we have a wide variety of "extras" (things like libraries, debuggers, static analysis tools, etc) available for our C code that aren't available for assembly language code. Even if we wanted to write a pure-assembly program, we would not be able to because several critical hardware libraries are only available as C libs. In one sense, it's a chicken/egg problem. People are driven away from assembly because there aren't as many libraries and development/debug tools available for it, but the libs/tools don't exist because not enough people use assembly to warrant the effort creating them.
In the end, there is a time and a place for just about any language. People use what they are most familiar and productive with. There will probably always be a place in a programmer's repertoire for assembly, but most programmers will find that they can write code in a higher-level language that is almost as efficient in far less time.
When you are writing in assembly, you don't have to write just in instruction codes. You can use macros and procedures and your own conventions to make various abstractions to make programs more modular, more maintainable and easier to read.
So what you're basically saying is, that with skilled use of a sophisticated assembler, you can make your ASM code closer and closer to C (or anyway another low-ish-level language of your own invention), until eventually you are just as productive as a C programmer.
Does that answer your question? ;-)
I don't say this idly: I have programmed using exactly such an assembler and system. Even better, the assembler could target a virtual processor, and a separate translator compiled the output of the assembler for a target platform. Much as happens with LLVM's IF, but in its early forms pre-dating it by about 10 years. So there was portability, plus the ability to write routines for a specific target asssembler where required for efficiency.
Writing using that assembler was about as productive as C, and with by comparison with GCC-3 (which was around by the time I was involved) the assembler/translator produced code that was roughly as fast and usually smaller. Size was really important, and the company had few programmers and was willing to teach new hires a new language before they could do anything useful. And we had the back-up that people who didn't know the assembler (e.g. customers) could write C and compile it for the same virtual processor, using the same calling convention and so on, so that it interfaced neatly. So it felt like a marginal win.
That was with multiple man-years of work in the bag developing the assembler technology, libraries, and so on. Admittedly much of which went into making it portable, if it had only ever been targeting one architecture then the all-singing all-dancing assembler would have been much easier.
In summary: you may not like C, but it doesn't mean that the effort of using C is greater than the effort of coming up with something better.
Assembly is not portable between different microprocessors.
The same reason we don't go to the bathroom outside anymore, or why we don't speak Latin or Aramaic.
Technology comes along and makes things easier and more accessible.
EDIT - to cease offending people, I've removed certain words.
Why? Simple.
Compare this :
for (var i = 1; i <= 100; i++)
{
if (i % 3 == 0)
Console.Write("Fizz");
if (i % 5 == 0)
Console.Write("Buzz");
if (i % 3 != 0 && i % 5 != 0)
Console.Write(i);
Console.WriteLine();
}
with
.locals init (
[0] int32 i)
L_0000: ldc.i4.1
L_0001: stloc.0
L_0002: br.s L_003b
L_0004: ldloc.0
L_0005: ldc.i4.3
L_0006: rem
L_0007: brtrue.s L_0013
L_0009: ldstr "Fizz"
L_000e: call void [mscorlib]System.Console::Write(string)
L_0013: ldloc.0
L_0014: ldc.i4.5
L_0015: rem
L_0016: brtrue.s L_0022
L_0018: ldstr "Buzz"
L_001d: call void [mscorlib]System.Console::Write(string)
L_0022: ldloc.0
L_0023: ldc.i4.3
L_0024: rem
L_0025: brfalse.s L_0032
L_0027: ldloc.0
L_0028: ldc.i4.5
L_0029: rem
L_002a: brfalse.s L_0032
L_002c: ldloc.0
L_002d: call void [mscorlib]System.Console::Write(int32)
L_0032: call void [mscorlib]System.Console::WriteLine()
L_0037: ldloc.0
L_0038: ldc.i4.1
L_0039: add
L_003a: stloc.0
L_003b: ldloc.0
L_003c: ldc.i4.s 100
L_003e: ble.s L_0004
L_0040: ret
They're identical feature-wise.
The second one isn't even assembler but .NET IL (Intermediary Language, similar to Java's bytecode). The second compilation transforms the IL into native code (i.e. almost assembler), making it even more cryptical.
I'd guess ASM on even x86(_64) makes sense in cases where you gain a lot by utilizing instructions that are difficult for a compiler to optimize for. x264 for example uses a lot of asm for its encoding, and the speed gains are huge.
I'm sure there are many reasons, but two quick reasons I can think of are
Assembly code is definitely harder to read (I'm positive its more time-consuming to write as well)
When you have a huge team of developers working on a product, it is helpful to have your code divided into logical blocks and protected by interfaces.
One of the early discoveries (you'll find it in Brooks' Mythical Man-Month, which is from experience in the 1960s) was that people were more or less as productive in one language as another, in debugged lines of code per day. This obviously isn't universally true, and can breaks when pushed too far, but it was generally true of the high-level languages of Brooks' time.
Therefore, the fastest way to get productivity would be to use languages where one individual line of code did more, and indeed this works, at least for languages of complexity like FORTRAN and COBOL, or to give a more modern example C.
Portability is always an issue -- if not now, at least eventually. The programming industry spends billions every year to port old software which, at the time it was written, had "obviously" no portability issue whatsoever.
There was a vicious cycle as assembly became less commonplace: as higher level languages matured, assembly language instruction sets were built less for programmer convenience and more for the convenience of compilers.
So now, realistically, it may be very hard to make the right decisions on, say, which registers you should use or which instructions are slightly more efficient. Compilers can use heuristics to figure out which tradeoffs are likely to have the best payoff. We can probably think through smaller problems and find local optimizations that might beat our now pretty sophisticated compilers, but odds are that in the average case, a good compiler will do a better job on the first try than a good programmer probably will. Eventually, like John Henry, we might beat the machine, but we might seriously burn ourselves out getting there.
Our problems are also now quite different. In 1986 I was trying to figure out how to get a little more speed out of small programs that involved putting a few hundred pixels on the screen; I wanted the animation to be less jerky. A fair case for assembly language. Now I'm trying to figure out how to represent abstractions around contract language and servicer policy for mortgages, and I'd rather read something that looks close to the language that the business folks speak. Unlike LISP macros, Assembly macros don't enforce much in the way of rules, so even though you might be able to get something reasonably close to a DSL in a good assembler, it'll be prone to all sorts of quirks that won't cause me problems if I wrote the same code in Ruby, Boo, Lisp, C# or even F#.
If your problems are easy to express in efficient assembly language, though, more power to you.
Ditto most of what others have said.
In the good old days before C was invented, when the only high level languages were things like COBOL and FORTRAN, there were lots of things that just weren't possible to do without resorting to assembler. It was the only way to get the full breadth of flexibility, to be able to access all the devices, etc. But then C was invented, and almost anything that was possible in assembly was possible in C. I have written very little assembly since then.
That said, I think it is a very useful exercise for new programmers to learn to write in assembler. Not because they would actually use it much, but because then you understand what is really happening inside the computer. I've seen lots of programming errors and inefficient code from programmers who clearly have no idea what's really happening with the bits and bytes and registers.
I've been programming in assembly now for about a month. I often write a piece of code in C and then compile it to assembly to assist me. Perhaps I am not utilizing the full optimizing power of the C compiler but it appears that my C asm source is including unnecessary operations. So I am beginning to see that the talk of a good C compiler outperforming a good assembly coder is not always true.
Anyways, my assembly programs are so fast. And the more I use assembly the less time it takes me to write out my code because it's really not that hard. Also the comment about assembly having poor legibility is not true. If you label your programs correctly and make comments when there is additional elaboration needed you should be all set. In fact in ways assembly is more clear to the programmer because they are seeing what is happening at the level of the processor. I don't know about other programmers but for me I like knowing what's happening, rather than things being in a sort of black box.
With that said the real advantage of compilers is that a compiler can understand patterns and relationships and then automatically code them in the appropriate locations in the source. One popular example are virtual functions in C++ which requires the compiler to optimally map function pointers. However a compiler is limited to doing what the maker of the compiler allows the compiler to do. This leads to programmers sometimes having to resort to doing bizarre things with their code , adding coding time, when they could have been done trivially with assembly.
Personally I think the marketplace heavily supports high level languages. If assembly language was the only language in existence today then their would be about 70% less people programming and who knows where our world would be, probably back in the 90's. Higher level languages appeal to a broader range of people. This allows a higher supply of programmers to build the needed infrastructure of our world. Developing nations like China and India benefit heavily from languages like Java. These countries will fast develop their IT infrastructure and people will become more interconnected. So my point is that high level languages are popular not because they produce superior code but because they help to meet demand in the world's marketplaces.
I'm learning assembly in comp org right now, and while it is interesting, it is also very inefficient to write in. You have to keep alot more details in your head to get things working, and its also slower to write the same things. For example, a simple 6 line for loop in C++ can equal 18 lines or more of assembly.
Personally, its alot of fun learning how things work down at the hardware level, and it gives me greater appreciation for how computing works.
What C has over a good macro assembler is the language C. Type checking. Loop constructs. Automatic stack management. (Nearly) automatic variable management. Dynamic memory techniques in assembler are a massive pain in the butt. Doing a linked list properly is just down right scary compared to C or better yet list foo.insert(). And debugging - well, there's no contest on what is easier to debug. HLLs win hands down there.
I've coded nearly half my career in assembler which makes it very easy for me to think in assmebler. it helps me to see what the C compiler is doing which again helps me write code that the C compiler can efficiently handle. A well thought out routine written in C can be written to output exactly what you want in assembler with a little work - and it's portable! I've already had to rewrite a few older asm routines back to C for cross platform reasons and it's no fun.
No, I'll stick with C and deal with the occasional slight slowdown in performance against the productivity time I gain with HLL.
I can only answer why I personally don't write programs in assembly more often, and the main reason is that it's more tedious to do. Also, I think that it is easier to get things subtly wrong without noticing immediately. E.g., you might change the way you use a register in one routine but forget to change this in one place. It'll assemble fine and you may not notice until much later.
That said, I do think there are still valid uses for assembly. For instance, I have a number of pretty optimised assembly routines for processing large amounts of data, using SIMD and following the paranoid "every bit is sacred"[quote V.Stob] approach. (But note that naive assembly implementations are often a lot worse than what a compiler would generate for you.)
C is a macro assembler! And it's the best one!
It can do nearly everything assembly can, it can be portable and in most of the rare cases where it can't do something you can still use embedded assembly code. This leaves only a small fraction of programs that you absolutely need to write in assembly and nothing but assembly.
And the higher level abstractions and the portability make it more worthwhile for most people to write system software in C. And although you might not need portability now if you invest a lot of time and money in writing some program you might not want to limit yourself in what you'll be able to use it for in the future.
People seem to forget that there is also the other direction.
Why are you writing in Assembler in the first place? Why not write the program in a truly low level language?
Instead of
mov eax, 0x123
add eax, 0x456
push eax
call printInt
you could just as well write
B823010000
0556040000
50
FF15.....
That has so many advantages, you know the exact size of your program, you can reuse the value of instructions as input for other instructions and you do not even need an assembler to write it, you can use any text editor...
And the reason you still prefer Assembler about this, is the reason other people prefer C...
Because it's always that way: time pass and good things pass away too :(
But when you write asm code it's totally different feeling than when you code high-level langs, though you know it's much less productive. It's like you're a painter: you are free to draw anything you like the way you like with absolutely no restrictions(well, only by CPU features)... That is why I love it. It's a pity this language goes away. But while somebody still remembers it and codes it, it will never die!
$$$
A company hires a developer to help turn code into $$$. The faster that useful code can be produced, the faster the company can turn that code into $$$.
Higher level languages are generally better at churning out larger volumes of useful code. This is not to say that assembly does not have its place, for there are times and places where nothing else will do.
The advantage of HLL's is even greater when you compare assembly to a higher level language than C, e.g. Java or Python or Ruby. For instance, these languages have garbage collection: no need to worry about when to free a chunk of memory, and no memory leaks or bugs due to freeing too early.
As others mentioned before, the reason for any tool to exist is how efficiently it can work. As HLLs can accomplish the same jobs as many lines of asm code I guess it's natural for assembly to be superseded by other languages. And for the close-to-hardware fiddling - there's inline assembly in C and other variants as per language.
Dr. Paul Carter in says in the PC Assembly Language
"...a better understanding of how
computers really work at a lower level
than in programming languages like
Pascal. By gaining a deeper
understanding of how computers work,
the reader can often be much more
productive developing software in
higher level languages such as C and
C++. Learning to program in assembly
language is an excellent way to
achieve this goal."
We've got introduction to assembly in my college courses. It'll help to clear concepts. However I doubt any of us would write 90% of code in assembly. How relevant is in-depth assembly knowledge today?
Flipping through these answers, I'd bet 9/10 of the responders have never worked with assembly.
This is an ages old question that comes up every so often and you get the same, mostly misinformed answers. If it weren't for portability, I'd still do everything in assembly myself. Even then, I code in C almost like I did in assembly.
I am an electronics student and I have programmed mostly in Assembly. Last night I saw an amazing article that discussed writing a compiler in Ruby. What the author had done was use GCC to peek how the C translates to Assembly. That resonated a lot for me. I could finally see how the C program translated to Assembly.My question/request to the community here is: Could you show me resources that discusses the link between those two better? Should I be reading about compilers? Should I be learning System programming? I dont know what to do. I really want to be better at programming and learn this better. Thank you for your help.
Related:
Learning to write a compiler
Is it beneficial for a programmer to learn how to build a compiler?
Can someone tell me the very basics of how computer programming works?
and others...
There really are a couple things going on here. First thing you should look at is something like a compilers book. There are several old ones, like the famous Dragon book, that are very good. I just discovered another one today, through, from the same guy who wrote the Art of Assembly Language Programming, on How to Write Great Code. I've only read the sample chapters so far, but it looks very good and also seems to address just what you want without dropping immediately into the wonders of LALR(1) grammars and so on.
"Systems programming" is more about, well, programming systems. In a systems programming ouse, you learn about using various system calls and other stuff to build useful programs. You need to know that too, but it's a different track than "how it happens."
A computer organization book, like the one aaronis refers to, is more about how the program gets from the assembly language level to actual gates and such. It's also called "computer architecture", as the phrase was used when Amdahl, Blaauw, and Brooks invented the term: instruction sets, how they're implemented, and how you make quantitative choices in the design of the things.
The classic reference text on compilers is Aho and Ullman, Principles of Compiler Design, aka the dragon book. The current edition has a few more authors and an updated title....
Compilers: Principles, Techniques, and Tools
When I took a Computer Organization class they went through the low level details of how processors have come to be, how they process instructions, and how assembly is translated into machine code. Maybe a little lower than what you are looking for, but I think getting a glimpse of how this type of translation occurs from a higher level language to a lower level language is really neat. I think we used this book or one similar:
http://www.amazon.com/Computer-Organization-Design-Interface-Architecture/dp/1558606041
Another good resource is Alan Holub's Compiler Design in C.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Being an aspiring Apple developer, I want to get the opinions of the community if it is better to learn C first before moving into Objective-C and ultimately the Cocoa Framework?
My gut says learn C, which will give me a good foundation.
I would learn C first. I learned C (and did a lot in C) before moving to Obj-C. I have many colleagues who never were real C programmers, they started with Obj-C and learned only as much C as necessary.
Every now and then I see how they solve a problem entirely in Obj-C, sometimes resulting in a very clumsy solutions. Usually I then replace some Obj-C code with pure C code (after all you can mix them as much as you like, the content of an Obj-C method can be entirely, pure C code). Without any intention to insult any Obj-C programmer, there are solutions that are very elegant in Obj-C, these are solutions that just work (and look) a lot better thanks to objects (OOP programming can make complex programs much more lovely than functional programming; polymorphism for example is a brilliant feature)... and I really like Obj-C (much more than C++! I hate the C++ syntax and some language features are plain overkill and lead to bad development patterns IMHO); however, when I sometimes re-write Obj-C code of my colleagues (and I really only do so, if I think this is absolutely necessary), the resulting code is usually 50% smaller, needs only 25% of the memory it used before and is about 400% faster at runtime.
What I'm trying to say here: Every language has its pros and cons. C has pros and cons and so does Obj-C. However, the really great feature of Obj-C (that's why I even like it more than Java) is that you can jump to plain C at will and back again. Why this is such a great feature? Because just like Obj-C fixes many of the cons of pure C, pure C can fix some of the cons of Obj-C. If you mix them together you'll receive a very powerful team.
If you only learn Obj-C and have no idea of C or only know the very basics of it and never tried how elegantly it can solve some common problems, you actually learned only half of Obj-C. C is a fundamental part of Obj-C. The ability to use C at any time and everywhere is a fundamental feature of it.
A typical example was some code we used that had to encode data in base64, but we could not use an external library for that (no OpenSSL lib). We used a base64 encoder, entirely written using Cocoa classes. It was working okay, but when we made it encode 200 MB of binary data, it took an eternity and the memory overhead was unacceptable. I replaced it with a tiny, ultra compact base64 encoder written entirely as one C function (I copied the function body into the method body, method took NSData as input and returned NSString as output, however inside the function everything was C). The C encoder was so much more compact, it beat the pure Cocoa encoder by the factor 8 in speed and the memory overhead was also much less. Encoding/Decoding data, playing around with bits and similar low level tasks are just the strong points of C.
Another example was some UI code that drew a lot of graphs. For storing the data necessary to paint the graphs, we used NSArray's. Actually NSMutableArray's, since the graph was animated. Result: Very slow graph animation. We replaced all NSArray's with normal C arrays, objects with structs (after all graph coordinate information is nothing you must have in objects), enumerator access with simple for loops and started moving data between the arrays with memcopy instead of taking data from one array to the other one, index for index. The result: A speed up by the factor 4. The graph animated smoothly, even on older PPC systems.
The weakness of C is that every more complex program gets ugly in the long run. Keeping C applications readable, extensible and manageable demands a lot of discipline of a programmer. Many projects fail because this discipline is missing. Obj-C makes it easy for you to structure your application using classes, inheritance, protocols and so on. That said, I would not use pure C functionality across the borders of a method unless necessary. I prefer to keep all code in an Objective-C app within the method of an object; everything else defeats the purpose of an OO application. However within the method I sometimes use pure C exclusively.
You can readily enough learn C and Objective-C at the same time -- there's certainly no need to learn the minutiae of C (including pointer arithmetic and so on) before starting with Objective-C's additions to the language, and as a novice programmer getting underway with Objective-C quickly may help you to start "thinking in objects" more quickly.
In terms of available resources, Apple's documentation does typically assume familiarity with C, so starting with The Objective-C 2.0 Programming Language won't be of much benefit to you. I would invest in a copy of Programming in Objective-C by Stephen Kochan (depending on how quickly you want to get underway, you may consider waiting for the second edition):
Programming Objective-C Developers Library
Programming Objective-C 2.0 Developers Library
It assumes no prior experience, and teaches you Objective-C and as much C as you need.
If you're feeling a little ambitious, you might start with Scott Stevenson's "Learn C" Tutorial, but it does have some prerequisites ("You should already know at least one scripting or programming language, including functions, variables and loops. You'll also need to type commands into the Mac OS X Terminal.").
(Just for the record and for context: I learned both at the same time back in 1991 -- it didn't seem to do me any harm. I did, though, have a background in BASIC, Pascal, Logo, and LISP.)
I thought a lot about this issue before writing my book on Objective-C. First, I really believe that learning the C language before learning Objective-C is the wrong path. C is a procedural language containing many features that are not necessary for programming in Objective-C, especially at the novice level. In fact, resorting to some of these features goes against the grain of adhering to a good object-oriented programming methodology. It’s also not a good idea to teach all the details of a procedural language (and attacking a problem's solution with functions and structured programming techniques) before learning an object-oriented one. This can start the programmer off in the wrong direction potentially leading to developing the wrong orientation and mindset for fostering a good object-oriented programming discipline. Just because Objective-C is an extension to the C language doesn’t mean you have to learn C first!
I think that teaching Objective-C and the underlying C language as a single integrated language is the right approach. There's no reason to learn that a "for" statement is from the C language and not from its superset Objective-C language. Further, why learn in detail about things like C arrays and strings (and manipulating them) before learning about array (NSArray) and string objects (NSString), for example? Many C texts devote a lot of time to structures, and pointers to structures, and iterating through arrays with pointers. But you can start writing Objective-C programs without knowing about any of these C language features. And for a novice programmer, that's a big deal. Not only does that shorten the learning curve but also reduces the amount of material that has to be learned (and some of it selectively filtered out) to writing Objective-C programs.
I do agree that you will want to learn most, if not all, of the underlying C features, but many can be deferred until a solid grasp of defining classes and methods, working with objects and message expressions, and understanding the concepts of inheritance and polymorphism are well-understood.
I'd dive right in with Objective C - if you've already got a few languages under your belt, it's not the syntax which is the learning curve, it's Cocoa.
I think that, for the most part, learning C is a good idea no matter what arena you're going in to, at least to get the hang of the inner workings of software development before using prepackaged goods, that way if something goes wrong you have a better chance of understanding the inner workings. There's plenty of discussion about this on SO, and it's a rather subjective question, but in general you will inherently be using C within your Objective-C code, so I guess it's really up to you. I'm a ground up kind of person, but sometimes it can get in the way and I know several smart people who worked their way from the top down, I think the important part is that you get to understanding the inner workings as it will set your capabilities apart from those who don't as well as increase your capabilities.
It's a good idea to learn C before learning Objective-C, which is a strict superset of C. This means that Objective-C can support all normal C code, so the code common to C programs is bound to show up even in Objective-C code.
In addition to looking at things purely from a language point of view, you will find that Mac OS X is a complete Unix operating system. All the system level libraries are written in C.
It is probably possible to learn both at the same time, but I think you will appreciate and understand Objective-C more if you have a solid working knowledge of C first.
I'd learn Objective-C and learn as much C as you need as you go along.
The areas of C that you won't depend on much:
Pointer arithmetic and arrays. I haven't used C arrays at all.
C strings. Objective-C's strings do the job nicer and safer.
Manual memory management if you use GC in Obj-C 2.1. I highly recommend this route for development speed and performance reasons.
As you learn Objective-C and Cocoa, you cannot avoid learning bits of C. For example, rectangles are common represented by CGRect, a C struct.
If you have time, by all means learn C. As others have said here, Kochan's book (second and first editions) is excellent as a book to dip into.
There are a lot of things you can't do purely in Objective-C, so learning some basic C skills will be pretty critical. You'll at least need to understand variable declarations and the basic C library functions, or you'll be frustrated.
Honestly, so many languages are based on the C syntax that it's a good thing to be familiar with. I'd take a week or two to familiarize yourself with C regardless.
That said, I did just teach myself Objective C, and I have to be honest: I didn't find my C experience to be as useful as I would have thought. Objective C was definitely eye-opening for me.
You can jump directly into Objective-C, with the following benefits:
You'll learn "some" C in the way.
You'll learn the C parts that are relevant for you .
At least for me is easier to learn a new language when I'm interested in some specific app or sample, and I fail when I have to learn other thing that is not exactly what I'm interested on.
You can always refine your C knowledge later if you get interested in lower level programming.
Better, I don't know, even less as I am not familiar with Objective-C.
But bases of C aren't so hard to learn, it isn't a very complex language (in terms of syntax, not in terms of mastering!), so go for it, it won't be wasted time.
Personally, I think it is always a good idea to learn C, it gives a good insight of how computer works. After all, most languages and systems are still written in C. Then move on! :-)
PS.: By "move on", I didn't mean "drop it", just "learn more, learn different". Once you know C, you might never drop it: Java uses JNI to call C routines for low level stuff, Python, Lua, etc. are often extended with C code (Lua reference even just assumes some C knowledge for some functions which are just a thin wrapper to the C function behind), and so on.
Yes, learning C language before any other advanced langauges will help you to learn quiclky other langauges.
According to Wikipedia, Objective-C is a strict super-set of C. This being the case, I would suggest learning C first. Then when you learn Objective-C it will be clear what parts are added as part of Objective-C.
C gives you very little abstraction from assembly. Some C Compilers will even let you inline assembly. This can be very useful for thinking about how the computer works, which is important to know.
That being said, if you're really interested in Object-C don't let yourself get stuck writing something in C just because its "good for you". You don't need to frustrate yourself while you're trying to learn a new skill set. It is important that you have fun with what you're doing.
Do you want to be a hard-core developer? Then learn c first.
The books you need to completely master c are some of the best writings in technology. Here's what you need:
C Programming Language
The Standard C Library
Objective C is sufficiently different from C as to not merit learning C first.
From a syntax / language-family perspective one is almost better off studying SmallTalk (on which objective C is based)
From a practical perspective, focus your efforts on learning one language at a time.
Later, if you wish to learn another language, C++, Java and Python are 1) easy to learn as a bunch 2) popular and thus marketable 3) powerful.
You should have a basic knowledge of C before starting Objective_C, but there's no need master every detail of C.
I've published my notes after reading "Programming in Objective-C" in case it helps someone else.
learn objective c with programming-
Depending on many languages you already know it may be a better idea to just start learning Objective-C. The foundation in most languages are basically the same, it's the syntax that is different. Learning C first isn't really going to make much of a difference when it comes to learning Objective-C.
I learned Objective-C straight away and it worked fine for about a year now, I just had some difficulty reading C code when I downloaded project to see how they work, but now I really feel the need to learn C. You can try learning ObjC without C, but sooner or later, you will need C.
IMHO one should first learn at least some C and especially about pointers. That’s even more important if one comes from a language that doesn’t have pointers. A lot of people ask about code like
NSString *string = [[NSString alloc] init];
string = #"something";
since they don’t know about the distinction between a pointer and the object it points to.
Of course one doesn’t have to learn all of C before one can start with Objective-C, but some fundamental things are absolutely necessary.
Heck no, go straight to objective C!
I moved from ActionScript 3 to Objective C, and I already have an intern at a company!
Do what you want.
If you learn some other language prior, then you will always have confusion in writing right syntax. I do not know purpose, but Object C uses weird (not common) syntax for calling object methods. It names it as sending messages, yes, it is true accordingly pure Object Oriented concept, however most Object oriented languages name that as calling method and use more traditional syntax of calling methods. Garbage collection is also something very odd, Object C is based on old school reference count. So you will have difficulties to accept it if you switch from other language.
I am writing a book Object C quick migration guide for C/C++ programmers hoping to help people to pickup all differences quicker.