C is a language used by many a programmer, and it is an interesting language. But here’s the thing, it was never designed to teach people how to program. It’s a great language for people who have a basic understanding of programming principles, but for a novice programmer, it just doesn’t make the grade. Let’s explore why.
Let’s start off with the good. C only uses 32 reserved keywords, which is extremely good from the perspective of learning the entirety of the language. On the other end of the scale, Java has 50, and C++ has the 32 keywords of C, with an additional 30 keywords, for a total of 62. So, C has brevity on its side, which is good. C also allows for access to low-level programming, some have likened it to “assembler with steroids”. This is a double edged sword, because it makes the language powerful, but it also makes it unwieldy for a novice programmer. It is also a very powerful language, and that is best illustrated by the fact that a number of compilers for other languages are written in C. However Python has 33 keywords and is inherently easier to deal with.
C is also a pure language, unlike many other languages are multi-paradigm, or use concepts such as OO. Not that OO is bad, it’s just a real distraction to have to deal with concepts such as inheritance and polymorphism. However if you learn C, it is easier to transition to languages with a similar structure, such as C++, and even Java. Other good things? I have to strain to think of some… for the novice anyway.
For the novice programmer, who knows very little about the intricacies of memory, C can be a horrible language to learn to program in. This manifests itself in the first time a programmer writes a scanf() statement. Consider this piece of code:
int nmbr; scanf("%d", &nmbr);
To a veteran programmer, this is not an issue. To a novice, they are forced to understand that the ampersand character in the clause &nmbr is used to store the value input by the user from the keyword in the memory position associated with the integer variable nmbr. Quite a daunting task. Failure to add the & will result in a problem int he form of a Segmentation fault: 11. But the compiler *will* compile the code, giving the programmer the false sense of security by thinking that their code is okay. This could not be further from the truth. Now the novice programmer has to try and figure out what a Segmentation fault: 11 means.
This reliance on memory does not go away. It forces itself upon the programmer again in the guise of pointers in the context of function parameters, and dynamic memory if a large amount of space is need to store some piece of data. It can also inadvertently appear in the form of insufficient memory associated with the stack. You have to understand memory to program in C, it’s unavoidable. In addition, C allows programs with errors to run. Consider the following code:
int a = 0; if (a = 1) printf("valid");
C allows assignment statements within an if conditional, so the fact that a is set to equal 1, means that the condition will always be true, regardless of what a‘s value is coming into the if statement. There are also deep issues with a failure to check array bounds, and overwriting memory.
Ugliness in C manifests itself in the compactness of the language. Firstly through the use of compact operators such as ++, ––, &&, ||, += etc. These operators likely made a lot of sense when C was first introduced, because they likely helped reduce machine instructions (many were first used in preceding language such as CPL, BCPL, B, etc). However to the novice programmer, the i=i+1 is inherently easier to write than i++, because it is understandable (once they get past i=i+1 as a programming statement, not a mathematical one). The use of operators such as ++ serve to confuse the novice programmer, because in certain contexts such as:
int p = 4; p++; printf("%d", p);
The value of p is 5, whether or not p++ or ++p is used. However used in this context:
int p, x; p = 4; x = p++;
The value assigned to x is 4. Change p++ to ++p, and the value of x becomes 5. This is because p++ means “use the value of p, then increment p by 1, and ++p means “increment p by 1, and then use its value”. Subtle, yet bound to make an algorithm fail. The novice programmer doesn’t need this (and I would argue the rest of us don’t either). There are similar issues using && for and, etc.
There is also things like the way arrays are indexed. The most common way is something like a[x], where x is the index. However in C it is also possible to write x[a], which is super confusing for the novice. This is because a[x] means *(a+x) and x[a] means *(x+a).
Oh, and some control structures that have somewhat obtuse structures (e.g. switch), or lack consistency, such as the while and do-while loops. The while loop does not require enclosing parentheses, unless there is more than one statement. The do-while loop does require parentheses. Lack of consistency causes recall issues amongst novice programmers.
I add this last category, because frankly, C is a boring language. There are things that can be done with C, but it takes a good amount of experience with the language. Starting with the bare bones language, there is nothing inspiring which can be done. No graphics, no processing images, no fun stuff. So it is inherently hard to motivate novice programmers, when the pinnacle of fun is outputting Factorials, or a “cool” sorting algorithm.
One thought on “C language: The good, the badly, and the ugly”
Interesting post. I have written a few codes for C++ on my blog. I agree, sometimes C++ doesn’t feel like the write language to operate in.