# Do I need to learn C?

I am a PhD student in Scientific Computing and over the past few months, I spent a good amount of time learning Python and C++ the right way. I feel that I have learnt C++ well and I can use Python to do what I want if I keep a good reference book around.

I also know MATLAB enough to prototype my ideas and get solutions. (If I am too bored to code Python which is my first choice).

I have read multiple times here that one should club C and C++ into one "C/C++" because they are extremely different languages with different motives and I completely agree with that viewpoint.

Although I cannot claim to "know" C++ since I am always learning but I think I understand most of how I should use it and how I should use it not. The first language that I learnt was C but it has been very long since I last used it. My question is essentially this:

Given that I know MATLAB, C++ and Python; should I invest time in learning C? Will my knowledge of the mentioned 3 languages be enough for me to code?

My research is more on the numerical linear algebra side but I also do some discrete event simulation/stochastic processes consulting. My intention is to work in Industry (My advisor suggested I learn C++ so that I stay employable though he has no personal preferences of languages).

-
The difference between Fortran 60 and Fortran 2003 is larger than between C99 and C++98. And between 77 and 2003 is pretty much the same. Still, people call them "just" Fortran. – Misha Feb 2 '13 at 8:49
You should throw all these other languages and just learn Fortran ;) modern Fortran has everything you need for what you do. – Nasser Feb 2 '13 at 21:47
Whichever language you use, make sure you document any code that must be maintained, and include some examples and automated tests. If you're not doing that then you don't really know any language. – cjordan1 Feb 4 '13 at 18:13

I will address only the comparison of C to C++. While it is true that anything written in C can be ported to C++ with a few syntactic touch-ups, the communities have different values. The C library community, more than almost any other, values binary stability. Binary stability is critical for low-level libraries to avoid inflicting constant pain on those layers above, especially when used with a binary distribution model and shared libraries. C is the overwhelming preference for such libraries that need to just work, with the ability to ship new releases without recompiling layers above.

It is possible to ship C++ libraries that operate at this level, but you end up needing to "write C in C++". For example, you would never place a structure definition with private or virtual members in a public header, you would never use templates in a public interface, and you would never have an API based on inheritance from classes that have any data members. These constraints are necessary to precisely contain dependencies, so that you can modify your implementation without changing the binary interface. C tends to be much easier to bind from different languages, due to its simpler object model and well-defined ABI.

If you are writing code at the application level rather than the library level, then your binary interface is unimportant, so many of these concerns go away. Use of C++ language features like inheritance and templates still tend to produce more tightly coupled code, leading to more time-consuming recompilation as the project grows. In addition to more sprawling compile-time dependencies, simply compiling C code with a C++ compiler significantly increases compilation time (about 2x with most toolchains).

If these concerns interest you, or if you plan to work on lower-level libraries, then spending time on C may be worthwhile. If you like using C++ language features and aren't too bothered by binary interfaces and coupling tightness, then it may not be a good use of time. But keep C in mind if these things things start bothering you in the future.

-
There were so many awesome answers, it was hard to pick one but this was the most descriptive and complete in my opinion. +1 to everyone though. Thoroughly enjoyed reading so many perspectives. I decided I'll just keep perfecting C++ and learn C on a need basis. – Inquest Feb 2 '13 at 2:17
For completeness, might want to add the pimpl idiom is one way C++ coders can construct "compilation firewalls" so they won't have to recompile application code after underlying implementation changes. – cjordan1 Feb 4 '13 at 18:00

Rather than "learning C", I'd suggest that you're at a point now where you've done enough programming and worked with enough programming languages that you should focus instead on improving your programming technique and broader knowledge of computer science. Then learn C if and when you need it for a particular project.

Experienced programmers quickly pick up new programming languages as needed for particular projects. They can do this because they understand important concepts that translate from language to language- the syntax isn't much of a problem if you've mastered those higher level concepts. When you watch students trying to learn their second programming language, you'll often see them struggle with understanding some new concept that wasn't part of their first language. For example, students who start with Fortran often struggle with pointers in C. Students who know C often struggle with the object oriented features of C++, and so on.

-

The answer to this question really depends on what you really do.

As a Computer Scientist who does high-performance computing, I'd say it's essential to know/understand programming in C.

But if you're just doing stuff on computers, then your knowledge of C++ should be enough to get you through.

More specifically, if you're really interested in computational aspects, i.e. writing algorithms that get the most out of modern computers, you won't be able to avoid having to deal with low-level aspects such as memory management, data layouts, SIMD vectorization, instruction-level parallelism, shared-memory parallelism, or GPU computing (CUDA and OpenCL are based on C).

Now, most of these things can be taken care of by compilers (e.g. for memory management, data layouts, vectorization) and/or higher-level abstractions (e.g. OpenMP, OpenACC, optimized libraries). But only to a certain extent. Doing things by hand usually involves more work, but the payoff can be an order of magnitude in performance.

Basically, whenever you want to control the details yourself, you usually end up using C since it is "closer to the metal". The question is, however, is that what you really want?

-
How can you say C++ is any farther from the metal than C? What can you not do in C++ that you can do in C? And are you saying there are negligible useful features in C++ for low-level computation? – Milind R Mar 2 '13 at 21:03
@MilindR: Granted, you can compile a C program with a C++ compiler, so C++ can do everything that C does. The problem is with the extra features that C++ provides, e.g. polymorphic objects, templates, pipes, etc... Which do not map well to the actual "metal". If you use any of these features of C++, you lose control of what your program is actually doing, on an instruction-by-instruction basis. That is the point I was trying to make, and by which I stand. – Pedro Mar 2 '13 at 21:25
I agree about polymorphic objects, but how can templates take you any farther from the metal? I think you're referring to inheritance hierarchies here. Anything that doesn't use them are likely to be quite close to the metal. – Milind R Mar 2 '13 at 21:30
@MilindR: No. Say you use a template class for a vector of float or double. The actual operations on those vectors will be implemented in a way that is optimal for one, or for the other, but never for both. Inheritance hierarchies have the same problem as polymorphic objects: If you don't know the exact type at compile-time, you not only have a small overhead in selecting the correct function, but you also cannot inline the target function. – Pedro Mar 3 '13 at 11:50
That's what template specialization is for. Agree about not knowing type at compile time resulting in overhead. – Milind R Mar 4 '13 at 5:11

It is good to know C, and you can actually implement many of the OO features of C++ that are relevant to scientific computation in C without much trouble (it is very instructive to take a look at the source code for PETSC to see how they do it).

That said, there is no one-size-fits-all answer to this question. There are many factors in choosing a language, runtime being one of them. How long you spend writing,debugging,profiling code is another important factor. In the end you want to be as productive as possible. Knowing C will be great if you intend to get into the high performance side of research, or if you anticipate that your code will take an extremely long time to run (i.e. runtime trumps your coding workflow time). Otherwise if you know C++ and these things aren't an issue, you should be able to understand C code well enough to communicate with those who are using it.

-
But is C really that faster than C++ ? – Inquest Feb 1 '13 at 6:03
Programming languages aren't fast or slow a priori, it is the programmer that writes good code which determines its effectiveness. The benefit of C is that it's very simple, and writing efficient code in it is far easier than writing efficient code in C++ or Python (assuming here you are making full use of the language faculties). I have seen very fast C++ code utilizing its full capabilities that required rolling your own memory management and doing all sorts of nasty things with operator overloading, consider the time taken to write that versus an equivalent C version for the same speed. – Reid.Atcheson Feb 1 '13 at 6:08
@GeoffOxberry Some of the packages you mention are really written for flexibility (within some scope) far more than speed. Those written for absolute speed suffer from the difficult debugging, huge compilation time, and large binaries inherent in use of templates for much more than is truly necessary for performance. Of course you can write a "C" package in C++, but the community values are quite different. – Jed Brown Feb 1 '13 at 16:54
Furthermore, by "high performance" I didn't necessarily mean simply writing code of high performance. I meant on the research side of HPC, often dealing with lots of lower level details. these can be obscured using a C++ style of programming. This isn't necessarily a bad thing, but it depends on what your goals are. – Reid.Atcheson Feb 2 '13 at 1:28
In other words, if you are an HPC researcher then writing code with another package that just happens to be fast isn't really of much value research-wise. People will want to know why your code is faster and why your approach is effective, citing a package doesn't cut it. – Reid.Atcheson Feb 2 '13 at 1:34

There is a bit of copy-paste from my answer to this question, with a few extra details.

I work in industry (surveying and machine control equipment manufacturer) using weak embedded processors (think mobile phone processors), where about 50% of the computational grunt is spent doing numeric computations - mostly sensor fusion work.

We have at one mathematician working for us who used to work in a HPC group, so this is one of odd places where you may eventually find a job!

In this environment, where you will almost certainly have an operating system (e.g. Linux, QNX, WinCE), C++ is king. We use C only for kernel work (i.e. device drivers) and for deeply embedded work without an operating system (8-bit micros). We don't use C for any numeric work. Indeed, we don't have a FORTRAN compiler for our platform!

High performance matters to us because we only have a 1 Watt CPU for processing. Whilst we don't have some of the "glamourous" problems of parallelism, we have to be cache- and memory- aware, and increasingly need to be aware of SIMD (think NEON). What's more, unlike HPC, we have to acutely aware of latency (this is machine control!) and other operating system aspects like scheduling and context switching. Memory allocation is especially nasty in this environment as it almost certainly means a context switch ( == latency and, on a 400MHz CPU, expensive in terms of time).

These issues are independent of choice of language, so I am going to disagree with @Pedro's answer that C is necessary - after all, compiler intrinsics for SIMD are available when using C++. It does, however, mean that you have to very careful about which features of C++ you use and what they cost.

So, to complete the answer, no, you don't need C. We use MATLAB for analysis work and python for scripting so your two languages other than C++ are good choices - at least in my industry.

-

The value of c, such as it is these days, is that it forces you to become familiar with the functioning of the computer at a low level of abstraction (compared to, say python). Now, c++ has all the low-level facilities of c and could stand in just as well, but most people are encouraged when leaning c++ to avoid the lowest level abstractions and rely on the (well tested and debugged) high level ones; things like the container library, smart pointers, polymorphism and so on.

It makes sense for most programmers to spend most of their time playing in realms of high abstraction, because they can spend more mental time and energy writing what they mean than handling the picky little details of how you accomplish it.

The cost of that attitude is some risk of leaky abstractions biting you when you least expect it, but it almost certainly adds to overall programming efficiency.

So, if you are happy with what you know about the low level functioning of your computer you can safely put c off, and even if you are not, you could use a restricted set of c++ to accomplish the same thing.

-

I answered a similar question once on Stack Overflow. The obvious answer is to learn everything you can, right?

So let's look at the negative point of view. You already are more proficient in three languages that I would consider to be more valuable than C for scientific programming. In my consulting work writing scientific software I've used MATLAB, Python, FORTRAN, and Java. I've never had a need to use C or C++, but note that all of my work has been on new projects. I would not advise a client to start a large project in C/C++, but would recommend Java, or even Scala, unless there was some compelling reason to use C/C++. For a smaller project I would go with Python, probably. In your case, it looks like you could deal with C on an as-needed basis.

I would expect that learning more about the domains in which you will work will pay off more than being a language jockey. In the end, it's the problem solution, not the the tool, that matters. Knuth's saw about "premature optimization" applies to preparing for a career, as well.

-

It's probably not worth it.

C++ and C tend to occupy the same niches in computational science (maybe embedded systems are an exception). It used to be the case that C compilers were better (more feature complete, better at optimizing) than C++ compilers, but from what I understand now, that is no longer the case.

Sure, C is a wonderful language (and I prefer it to C++), and if you have the time and desire, I'd recommend learning it, but if you're strapped for time, I see no compelling reason other than "I need to work on a project that is being written in C" (and even then, a great deal of your C++ knowledge will carry over).

-

I think some C knowledge is useful, mainly to learn about how to compile things with "extern C" linkage so you can pull legacy C/Fortran libraries (e.g. lapack) into new C++ projects. I wouldn't invest much time into learning the legacy C libraries, that stuff can be picked up/googled as needed, or sometimes replaced with equivalent functionality in the C++ stdlib.

-