Programming in C, a workout for your brain cells

Programming in C is difficult and the reward is fast execution of the code. For someone learning C, there is also the reward of excellent brain cell exercise.

Thinking exercises your brain and is shown to extend your lifespan when you are not exposed to other dangers, like war, bushfires, or asbestos. You need to workout your brain the same as your body.

The guidelines for muscle exercise tell you to workout twice a week to maintain fitness and at least three times a week to improve fitness. Assuming the same is true for your brain, your should invest a few hours per day at least three days per week learning something new. Learning to program in C will exercise your brain.

Execution speed

I used to program in assembler, the only way to get machine speed. Execution of assembler code gives you access to 100% of machine speed and resources. Some machines have a straight forward architecture, giving you an easy to learn assembler language and the maximum execution speed.

C executes slower than assembler but can be faster than most other languages. C can perform basic operations using close to machine level instructions. C is a compromise based originally on a relatively simple machine. Doing anything complicated in C can take you a long way from machine level code, a reason why some other languages occasionally outperform C in very narrow bechmarks.

Other languages

Rust

Rust is a language that competes with C for most work. Rust is incredibly hard to learn because everything is complicated and often weird. C has a far simper code structure, compared to Rust, but is still difficult to learn because C is too primitive.

With C, you are attempting to do something intelligent but have to translate your idea to make use of the C language compromises then the C compiler makes an attempt at converting those compromises into something workable on the machine executing the code. Rust beats C in some benchmarks.

Assembler

The only disadvantage of a good assembler language is the requirement to write different code for different architectures. In previous decades, there were people who would not use Assembler because a company named Apple used an incredibly cheap processing chip with an odd architecture. You would have to use two different assembler languages. Add to that, Apple's cruel treatment of customers where Apple constantly changed the processor, forcing customers to buy everything again every couple of years. If you want to know how bad the Apple approach was, ask one of the thousands of application developers who were tricked into buying an Apple Lisa.

There are assembler languages that are difficult because the hardware architecture is difficult and there are versions of assembler that are difficult for the same reasons the C is difficult, bad language design choices. When the language does not match the hardware, you waste a lot of time trying to teach people that the hardware works one way and the language works another way.

Think about steering a car. The instructor tells you to turn left by turning the top of the steering wheel to the left. What would happen if one car manufacturer made a car where you have to turn the top of the wheel to the left when driving up a hill but the opposite way when driving down a hill? Make it more complicated. To turn on Tuesdays, you have to switch to a separate lever. The car steering wheel matches the movement of the handlebars on a bicycle. Imaging driving your first car with the steering set to be opposite to your bicycle.

There are assembler languages with stupid bits of design. C has pointers to confuse the beginner.

Java

Java might work today. Java was once promoted as WORA, Write Once, Run Anywhere. For decades it was Write Once, Works Nowhere. The Java execution speed was pathetic until Microsoft brought out their version with 20 times the speed. Sun Microsystems had to copy the brilliant changes from Microsoft. Performance was fixed. Sun Microsystems was still unable to make the language work.

Java was so bad you had to ship almost the whole development system with your application. You had to waste a massive amount of time changing your code for slight variations in different operating systems. C never had the problem of having to ship a giant development library. C does have the problem of changing some code depending on the operating system.

With Java, you also had to waste huge resources constantly changing your code to keep up with versions of Java. As a guide, there were times when Java changed so fast that your code was obsolete before you could make the changes for the previous version of Java. C was never that bad.

Across a decade, C changed by about the same amount as Java would change overnight. C development does suffer from the lack of improvements.

Pointers

As an example of complication, C requires the use of addresses called "pointers" but does not have a pointer data type. Instead you have to misuse the integer data type for pointers. The compiler then puts out truly frustrating useless messages based on inaccurate guesses about integers that might be pointers.

There are dozens of other examples caused by parts of the language not matching up with other parts of the language. C was created as a simplified version of an assembler language for a small old machine that appears to have not had much in the way of intelligence. C is locked into doing things in the old way due to the mass of C code out there.

The C style alternatives to C appear to be designed as a random pack of good ideas but without actually fixing the basic problems of C. When someone starts developing C version 2, the first change should be to make pointers an address data type distinct from integer.

Tutorials

Many people start learning C from a book named The C Programming Language by Dennis M. Ritchie and Brian W. Kernighan. This is a book written for people who know the language so well that they do not need a book. From what I can see of the thousands of pages of documentation on C pointers, most are just copies of the examples from the original C book but none explain pointers for the beginner.

C builds strings as character arrays with special features but nothing to make strings behave as strings. This funny half built system creates endless problems and almost as many questions as pointers. The online documentation suffers from a lack of consistent approach. You have add in extra libraries of code to get string style functions that are inconsistent in design. The libraries vary in content. You should either have strings implemented properly or not have them at all.

To make string processing more complicated, the add-on libraries give you extra extra string processing functions but vary from operating system to operating system and within versions of operating systems. Unfortunately important parts of string processing are not included everywhere, restricting tutorials to only what is common to "most" versions of C.

All the way through C, you run up against many different examples of "how to" do what you want without any of them working. You find you have to do things in different ways using just slightly different code because the language has inconsistencies that are difficult to explain. Th online page tells you to do one thing and warns against any other approach but their examples do not work. Forum answers provide alternatives then say something like "it is the right way to do it but it does not work on my computer".

In forums, you find answers to your questions but the top voted answer, marked as correct, does not work. Somewhere down in the middle are variations. You end up patching together random bits from a hundred answers in dozens of forums.

Think about a run through the countryside for exercise. There are many paths but they all lead to the wrong place. The C version would have signs pointing the wrong way. The C version would have deep mud in many tracks. You would stop running in C land.

Learning speed

Based on several attempts to learn C, C is the second worst language to learn. What should take ten minutes to learn and less than 30 minutes to produce working code, can easily waste six hours without you getting any closer to working code.

Java is the only language that I would rate as worse than C and that is because Java is so unreliable. Java can take less time to produce code that does something but Java takes much more time to produce something efficient to the extent that you can use it with significant amounts of data.

By the time you have a Java based program ready to release, Java has changed and you have to start again. C is more stable, both an advantage and something holding C back from long term development.

You get to think about your code in more detail because you have to write so much detail. Your massive pile of code requires good organisation. The lack of language facilities for structure makes you develop great organisation or give up.

Conclusion

C is frustrating but not as frustrating as Java or Rust. C is slow to write due to all the trivial detail you have to create. Outside of the stupidity with pointers and strings, learning C is solid exercise for your brain.