Home > General > The Dying Art of C Programming

The Dying Art of C Programming

June 21st, 2014

Most people think of C as a cruel mistress. To the contrary, C is a submissive slave. C will do exactly what you tell it to do. I’ve found that people that learn high level languages like PHP, Java, Ruby, and so on hate C because of how much work it is.

I recently came across a Ruby programmer that didn’t know C. The very idea of a programmer that doesn’t know C boggles my mind. He had a problem in Ruby which I solved by downloading the source code to Ruby (which is written in C) and figuring out what Ruby was actually doing.

The fact of the matter is that much like the old days when “real” programming was ASM, C abstracted the machine language out of the architecture at the lowest possible level. C is so awesome that it doesn’t even judge you on architecture. You can embed ASM directly into your C (although you probably shouldn’t).

So why do so many people hate C? It’s because C lets you fuck yourself over. And it does so happily. For instance this is a perfectly valid C program that will compile and execute properly:

#include 
#include 
#include 
int main(int argc, char *argv[]) {
	void *string;
	string = malloc(1);
	strcpy(string, "are you kidding me?  this works?");
	printf("%s\n", string);
}

Feel free to compile and run it yourself. It will happily run. But any C programmer will immediately tell you what is so horrendously wrong with this program. If you don’t understand why this program is horrifically bad — or more importantly why it works at all — then you cannot understand how the underlying system works.

Which brings me to the point: If you do not understand how the underlying system of your programming language works, then you will never be a good programmer.

So let’s look at the above program and why it’s so bad:

The includes grab the header files. These files define the functions you’re going to use. You can’t just randomly make a function in C and call it. It has to be defined. If you try to call an undefined function in C, the compiler will bitch and moan about it.

Next, we have the “main” function. The main function is always what gets executed first and it is always predefined as exactly:

int main(int argc, char *argv[])

Some compilers will disable warnings when you try to implement main differently, but if there is one thing you need to know about C, it is that main() is always defined this way. “int main(int argc, char *argv[])” is basically muscle memory for any C programmer. As an example:

#include 
#include 
#include 
main() {
        void *string;
        string = malloc(1);
        strcpy(string, "are you kidding me?  this works?");
        printf("%s\n", string);
}

The compiler will accept this, but will probably complain about it. Feel free to compile it yourself and run it. The compiler will complain, but the program will run.

Compilers aside, why is this program bad in the first place? It’s because I’ve allocated 1 byte of memory and then I copied 33 bytes of data into that memory space. At this point, the astute reader would say “are you kidding me? this works?” is only 32 bytes! The string library in C always adds a null character to the end. So your 32 byte string is using 32 bytes of memory.

So what the hell, C? How can I allocate 1 byte of memory and you let me put 33 bytes into it? Because like the honey badger, C doesn’t give a fuck.

It depends on architecture and implementation of “malloc()” but you generally cannot allocate a single byte of memory. When you call malloc(), you are given a “page” of memory, which is going to be more than 1 byte. If you want to find out how much memory malloc() allocates in a page, a simple C program can tell you:

#include 
#include 
#include 
int main(int argc, char *argv[]) {
	char *string;
	char *ptr;
	string = malloc(1);
	for (ptr = string; ptr < string+1024*1024; ptr++) {
		printf("%d\n", (int)(ptr-string));
		*ptr = 0;
	}
}

This will run until it crashes. When it crashes, the number that is output is the end of the page. This awesome little program is also a great example of another great feature of C: Pointers. Lots of high level languages hint at pointers with emulated pass by reference and whatnot, but this is where C shines. I don't want to get into how pointers work, but if you look at the above code and are confused, then you don't understand pointers.

All programmers of any language should know C. Even if you hate how it doesn't "do things for you." Even if it annoys you that there are no "objects" (hint: there are, but not like you're used to). Not learning C as a programmer is like hobbling yourself intentionally.

General

  1. July 1st, 2014 at 20:44 | #1

    Academics still give me large chuck of their syllabus towards learning C and I am sure people can never leave the charm of using C. Thanks for the article. Keep writing

  1. No trackbacks yet.