The C Programming Language

Author: Brian W. Kernighan, Dennis M. Ritchie
All Stack Overflow 79
This Year Reddit 70
This Month Reddit 12


by cbasschan   2019-08-24

No, you don't... and no, it isn't. Stop listening to these literary nobodies and start listening to your book. I asked which one you're reading because it seems like the method you're using to learn isn't working for you (hence, you asked this question here, which people who read books wouldn't usually ask).

Look, I see this a lot. It would seem far too many people want to learn "the C programming language" purely by studying one rather common implementation... and so they end up learning a subset of the language which has subtle non-portable quirks that evolve a life of their own over time, perhaps becoming bugs or security issues.

C does not have pass-by-reference. I shouldn't need to point out that passing a reference type by value is still pass-by-value, because that should be written in your textbook somewhere. Take a look at this page if you'd like to know more about the difference between pass-by-reference and pass-by-value.

>By definition, pass by value means you are making a copy in memory of the actual parameter's value that is passed in, a copy of the contents of the actual parameter.

I predict a response similar to the following:

>... ok but C allows you to mimic pass-by-reference using pass-by-value ...

A turing complete language can mimic any other turing complete language, by definition. What can't happen is a reliable conversation in English if we don't agree upon the definitions for the words we use... and I quote, from the C11 standard, section

>In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument

This squarely describes the assignment of a copy into a temporary or intermediate space ("the corresponding argument"), i.e. clearly pass-by-value...

by cbasschan   2019-08-24

Indeed, it's good to see I'm not the only one who strongly dislikes this website...

> Strings in C are the collection of characters. Strings are also known as an "Array of Characters".


That is utter nonsense! Quoting the C standard, you can see why:

C11/7.1.1p1: > A string is a contiguous sequence of characters terminated by and including the first null character. The term multibyte string is sometimes used instead to emphasize special processing given to multibyte characters contained in the string or to avoid confusion with a wide string. A pointer to a string is a pointer to its initial (lowest addressed) character. The length of a string is the number of bytes preceding the null character and the value of a string is the sequence of the values of the contained characters, in order.


There are multiple contradictions in the implication your website creates. Let us look at them in order specified above:


C11/7.1.1p1: >A string is a contiguous sequence of characters terminated by and including the first null character.


Where in your definition have you mentioned the terminating null character? Note that this implies a string doesn't necessarily span the entirety of the array and a string doesn't necessarily reside within an array at all.

C11/7.1.1p1: >A pointer to a string is a pointer to its initial (lowest addressed) character.


If we interpret your website literally, then a pointer to a string is a pointer to an array of characters. The declaration of a pointer to an array of n characters named unusual_string_pointer looks like this:

char (*unusual_string_pointer)[n];


This is unusual because it's very unlike the argument type accepted by our standard string functions. In addition to the implications I've mentioned earlier, from this most recent quote from the standard we can tell a string might begin mid-way through an array.

>The length of a string is the number of bytes preceding the null character and the value of a string is the sequence of the values of the contained characters, in order.

It's extremely common for newcomers to categorically confuse the concepts of strings and arrays, such that they believe strlen(string_in_array) would be sizeof string_in_array - 1. That is not necessarily the case, as this quote shows, yet your website does nothing to guide beginners past this common hurdle.

Moving on to some other quotes within your page here...

>Strings in C is a one-dimensional array.

It is trivial to construct a string that isn't stored within an array. With the caveat that the only safe string (that I can think of) to do this with is an empty string, and that you'll probably want to use the &address-of operator to do this, I'll leave this to you as an exercise. The key take-home point here is strings are (typically) stored in arrays, but aren't the arrays. You could say that prime numbers are (typically) stored in int, but that's not necessarily always the case.

>Strings in C are ended by the "NULL ('\0') character. >Strings are written in double quotes ("Programming") while the character is written inside a single quote ('A').

I wonder why you would assume the position of a teacher whilst confusing string literals for strings like this. Tell me, why isn't "Programming" ended by the "NULL ('\0') character in this text? To me it seems like you have two definitions merged into one, and they're contradicting each other.

I would also like to add that one example of a string (using the formal definition from 7.1.1p1 above) can be written using a character literal like so: '\0' (this is a hint for your exercise). A pointer to that string (also complying with the definition) can be written, without a declaration... and the length of that string (see 7.1.1p1 for this definition) can be written... all without declaring a single variable.

C11/footnode 78: >A string literal need not be a string (see 7.1.1), because a null character may be embedded in it by a \0 escape sequence.

As you can see from footnote 78, an attempt to place a \0 terminating character into a string literal is likely to cause a string literal that isn't a string. Furthermore, if we use string literals as initialisers for arrays that aren't large enough to store the terminating byte, the string literal won't be treated like a string, for example: char fubar[5] = "fubar"; // not a string.

Further common confusions appear in reality with our students, such that newcomers tend to think an array of characters is automatically a string and thus automatically contains a terminating null character... more utter nonsense which your website does nothing to quench... and to be clear on this, I expect more from an educator and was shocked to find you work at a university, teaching programming! This was the point at which I decided to start reporting you for misleading people (and plagiarism). You need to go back to university, as a student, and study C properly (without cheating on your exams).

To be clear on this, if you're going to use the writings of other people (like myself), you need to properly cite those writings. We've been down this road before; I threatened you with DMCA takedown, remember? Frankly, you disgust me. Our educators should know better... to think I am unemployed on a disability pension while you are employed in my dream position. You disgust me!

Even despite earlier making the erroneous statement that Strings are also known as an "Array of Characters", you go on to say...

> In C programming, strings are not used as a data type (like char, float, double, int etc.).

Don't you realise "Array of Characters" is a data type? You have mixed this last small ounce of truth that this page contains in gallons of utter rubbish, as demonstrated by the very next statement you make:

> Strings are declared like an array if you do not know what the arrays are? Then, first, you should read the arrays.

You're a hypocrite. If you don't know what constitutes C, then, prior to assuming the role of an I.T. professors assistant, you should read a book about C (and do the exercises, as you would expect of your students).

I'm not going to bother correcting all of your errors. It'd be less wasteful of my time to simply write my own textbook, and to be clear on that matter, there's nothing wrong with K&R2E. Your website exists without a purpose, and lies to people. What you should do, to be honest to your students and to the founding forefathers of the language, is redirect your entire domain to the Amazon page for K&R2E. Make an affiliate link, if you like, so that you get commissions on the sales... at least this way your students will learn the *actual** programming language, as opposed to your retarded imagination of it*.

by TheHyperB3ast   2019-08-24

K&R. If you're in a programming 101 class that involves C, just buy this book unless your prof tells you otherwise.

K&R has the reputation it has because they did an excellent job of balancing between "experienced programmers can use this as a reference" and "newbie programmers can use this as a starting point. Let me clarify: K&R will not make you a better programmer, but it is an excellent example of what industry professionals would consider to be a good piece of technical documentation.

If you're going to ever work with APIs or large amounts of technical documentation about software, this book will mirror the experience you get reading "good docs". In short, learning C from this books does an excellent job of showing you how much you'll have to figure out yourself and what information you should be expected to be given to you when working in the industry.

by MrNeurotypical   2019-07-21

I found it much easier to learn C first and then C++


BTW I don't use C++ anymore, just python and BASH.

by farrp2011   2019-07-21

by mawattdev   2019-07-21

Read K&R C and work through the examples. C Programming Language, 2nd Edition

by ekollof   2019-07-21

This is your new bible:



by pdoherty926   2019-07-21

I haven't read either of those, but I did enjoy and find a lot of value in K&R and 21st Century C.

by anonymous   2019-07-21

Since Objective C is an expansion of C, I suggest the C 'bible' from Kernichan and Ritchie.

by anonymous   2019-07-21

K & R. [Kernighan & Ritchie]

by Hymnosi   2019-07-21

You would probably benefit from a systems manual, on top of a general syntax book like K&R.

this is not based on any experience, just some research I did on my own. Unfortunately most C programming knowledge is locked up in textbooks or in reference documents. There isn't a ton of walkthrough style manuals for the language, despite how old it is.

by Nicholas-DM   2019-07-21

C and Python are both used lots, and are good choices. C++ is beautiful and difficult, and there is a shortage of excellent material to learn from.

If you go with C, which is fast and great and, on its own, relatively easy to learn, the following book is likely the best way to learn it. It is known affectionately as the 'K&R Bible'.

If you go with Python, most resources will teach you a decent chunk decently well. You'll likely have trouble moving to intermediate complexity programming, but will be able to find guidance when you get to it.

Good luck and have a great day!

by ijustwantanfingname   2019-07-21

It's very, very worthwhile if you're learning C. A bit dry, but very concise and easy to understand.

by anonymous   2019-07-21

Just read The C Programming Language and write code. If you're new to it then you need first-hand experience so you can learn what the subtleties are. Just reading a list won't help a huge amount.

by Adam N   2019-07-21

An RDF Triple is a statement which relates one object to another. For Example:

"gcc" "Compiles" "c" .
"gcc" "compiles" "Java" . 
"gcc" "compiles" "fortran" .
"gcc" "has a website at" <> .
"gcc" "has a mailing list at" <> .
"c" "is a" "programming language" .
"c" "is documented in" <> .
by anonymous   2019-07-21

I learned C before I learned Objective-C, but the two have their similarities and differences. All the if statements, for & while loops are all the same in C, but how you GTD is different. Your not really exposed to the whole pointer thing in Objective-C, but that is super important in C, and the only way to get that down is reading and practice. It may seem daunting, but once you get the hang of it, its not that bad. Functions are a bit different then methods syntactically and how their called, so you will have to learn that also, but if you get a good book ( it shouldn't be that hard. Just read up and practice!

I also highly recommend the Stanford iTunes-U programming paradigms class, helps a lot learning about pointers, after you have a basic knowledge! Being a young programmer, it definitely helped me get a good grasp of it all.

by anonymous   2019-01-13
  • Everything before standardization is generally called "K&R C", after the famous book, with Dennis Ritchie, the inventor of the C language, as one of the authors. This was "the C language" from 1972-1989.

  • The first C standard was released 1989 nationally in USA, by their national standard institute ANSI. This release is called C89 or ANSI-C. From 1989-1990 this was "the C language".

  • The year after, the American standard was accepted internationally and published by ISO (ISO 9899:1990). This release is called C90. Technically, it is the same standard as C89/ANSI-C. Formally, it replaced C89/ANSI-C, making them obsolete. From 1990-1999, C90 was "the C language".

    Please note that since 1989, ANSI haven't had anything to do with the C language. Programmers still speaking about "ANSI C" generally haven't got a clue about what it means. ISO "owns" the C language, through the standard ISO 9899.

  • In 1999, the C standard was revised, lots of things changed (ISO 9899:1999). This version of the standard is called C99. From 1999-2011, this was "the C language".

  • In 2011, the C standard was changed again (ISO 9899:2011). This version is called C11. Various new features like _Generic, _Static_assert and thread support were added to the language. The update had a lot of focus on multi-core, multi-processing and expression sequencing. From 2011-2017, this was "the C language".

  • In 2017, C11 was revised and various defect reports were solved. This standard in informally called C17 and was released as ISO 9899:2018. It contains no new features, just corrections. It is the current version of the C language.

"C99 strict" likely refers to a compiler setting forcing a compiler to follow the standard by the letter. There is a term conforming implementation in the C standard. Essentially it means: "this compiler actually implements the C language correctly". Programs that implement the C language correctly are formally called strictly conforming programs.

"GNU C" can mean two things. Either the C compiler itself that comes as part of the GNU Compiler Collection (GCC). Or it can mean the non-standard default setup that the GCC C compiler uses. If you compile with gcc program.c then you don't compile according to the C standard, but rather a non-standard GNU setup, which may be referred to as "GNU C". For example, the whole Linux kernel is made in non-standard GNU C, and not in standard C.

If you want to compile your programs according to the C standard, you should type gcc -std=c99 -pedantic-errors. Replace c99 with c11 if your GCC version supports it.

by anonymous   2019-01-13

Let me start off by saying something a little off topic:

Anyway, it looks like you're looking at the extra credit exercises from this chapter.

  • Another aside- I don't think this is an especially sensible exercise for learning (another answer pointed out the question isn't formed to make sense), so this discussion is going to get a little complex. I would instead recommend the exercises from Chapter 5 of K & R.

First we need to understand that pointers are not the same as arrays. I've expanded on this in another answer here, and I'm going to borrow the same diagram from the C FAQ. Here's what's happening in memory when we declare an array or a pointer:

 char a[] = "hello";  // array

a: | h | e | l | l | o |\0 |

 char *p = "world"; // pointer

   +-----+     +---+---+---+---+---+---+
p: |  *======> | w | o | r | l | d |\0 |
   +-----+     +---+---+---+---+---+---+

So, in the code from the book, when we say:

int ages[] = {23, 43, 12, 89, 2};

We get:

ages: | 23 | 43 | 12 | 89 | 2 |

I'm going to use an illegal statement for the purpose of explanation - if we could have said:

int *ages = {23, 43, 12, 89, 2}; // The C grammar prohibits initialised array
                                 // declarations being assigned to pointers, 
                                 // but I'll get to that

It would have resulted in:

      +---+     +----+----+----+----+---+
ages: | *=====> | 23 | 43 | 12 | 89 | 2 |
      +---+     +----+----+----+----+---+

Both of these can be accessed the same way later on - the first element "23" can be accessed by ages[0], regardless of whether it's an array or a pointer. So far so good.

However, when we want to get the count we run in to problems. C doesn't know how big arrays are - it only knows how big (in bytes) the variables it knows about are. This means, with the array, you can work out the size by saying:

int count = sizeof(ages) / sizeof(int);

or, more safely:

int count = sizeof(ages) / sizeof(ages[0]);

In the array case, this says:

int count = the number of bytes in (an array of 6 integers) / 
                 the number of bytes in (an integer)

which correctly gives the length of the array. However, for the pointer case, it will read:

int count = the number of bytes in (**a pointer**) /
                 the number of bytes in (an integer)

which is almost certainly not the same as the length of the array. Where pointers to arrays are used, we need to use another method to work out how long the array is. In C, it is normal to either:

  • Remember how many elements there were:

    int *ages = {23, 43, 12, 89, 2}; // Remember you can't actually
                                     // assign like this, see below
    int ages_length = 5;
    for (i = 0 ; i < ages_length; i++) {
  • or, keep a sentinel value (that will never occur as an actual value in the array) to indicate the end of the array:

    int *ages = {23, 43, 12, 89, 2, -1}; // Remember you can't actually
                                         // assign like this, see below
    for (i = 0; ages[i] != -1; i++) {

    (this is how strings work, using the special NUL value '\0' to indicate the end of a string)

Now, remember that I said you can't actually write:

    int *ages = {23, 43, 12, 89, 2, -1}; // Illegal

This is because the compiler won't let you assign an implicit array to a pointer. If you REALLY want to, you can write:

    int *ages = (int *) (int []) {23, 43, 12, 89, 2, -1}; // Horrible style 

But don't, because it is extremely unpleasant to read. For the purposes of this exercise, I would probably write:

    int ages_array[] = {23, 43, 12, 89, 2, -1};
    int *ages_pointer = ages_array;

Note that the compiler is "decaying" the array name to a pointer to it's first element there - it's as if you had written:

    int ages_array[] = {23, 43, 12, 89, 2, -1};
    int *ages_pointer = &(ages_array[0]);

However - you can also dynamically allocate the arrays. For this example code, it will become quite wordy, but we can do it as a learning exercise. Instead of writing:

int ages[] = {23, 43, 12, 89, 2};

We could allocate the memory using malloc:

int *ages = malloc(sizeof(int) * 5); // create enough space for 5 integers
if (ages == NULL) { 
   /* we're out of memory, print an error and exit */ 
ages[0] = 23;
ages[1] = 43;
ages[2] = 12;
ages[3] = 89;
ages[4] = 2;

Note that we then need to free ages when we're done with the memory:


Note also that there are a few ways to write the malloc call:

 int *ages = malloc(sizeof(int) * 5);

This is clearer to read for a beginner, but generally considered bad style because there are two places you need to change if you change the type of ages. Instead, you can write either of:

 int *ages = malloc(sizeof(ages[0]) * 5);
 int *ages = malloc(sizeof(*ages) * 5);

These statements are equivalent - which you choose is a matter of personal style. I prefer the first one.

One final thing - if we're changing the code over to use arrays, you might look at changing this:

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

But, you don't need to. The reason why is a little subtle. First, this declaration:

char *argv[]

says "there is an array of pointers-to-char called argv". However, the compiler treats arrays in function arguments as a pointer to the first element of the array, so if you write:

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

The compiler will actually see:

int main(int argc, char **argv)

This is also the reason that you can omit the length of the first dimension of a multidimensional array used as a function argument - the compiler won't see it.

by anonymous   2019-01-13

K&R and Stroustrup are classics, and eventually you should get them, but I don't think they are good introduction for C++ beginners. Thinking in modern C++ is thinking in classes, templates, exceptions, and streams, none of which available in C language.

I would recommend a college-level textbook on C++ like Deitel and Deitel. alt text

After playing around, you should focus on learning to write a class that behaves like a built-in class. That means providing a copy constructor, operator=, operator==, operator<<, etc.. Along the way you'll meet various concepts embedded in the language of C++. I would agree with others on Effective C++ is a must read once you are comfortable with the basics.

by Bizkitgto   2019-01-13

I'd start with Harvard's CS50 on edx, it's the best course you'll find anywhere bar none. The instructor, Dave Malan is world class. Check out CS50, and the sub r/cs50 has a lot of like minded people like you. (Note: this course is free)

Stackoverflow is your friend where you can ask any question you have or bounce ideas off of others.

Learn Java OOP (here is an excellent course): Java MOOC

Free Code Camp for web development

Build your own operating system: NAND2TETRIS

Cave of Programming : All kinds of programming

Open Source Society University: This is a solid path for those of you who want to complete a Computer Science course on your own time, for free, with courses from the best universities in the World.

r/arduino for some embedded programming fun!

.....and of course for anything under the sun: &

For BSD:

For Linux:

For x86 assembly: [How far down the rabbit hole do you want to go?]

Edit: Wow, my first Reddit Gold!! Thank-you so much kind people!!

Edit2: Colt Steele has a good web dev course and is highly recommended to do in parallel with freecodecamp

Edit3: The MIT Challenge is Scott Young's blog on how he completed the entire 4 year MIT Computer Science curriculum in 12 months

Edit 4: The Rails Tutorial by Michael Hartl is the Bible for learning Ruby on Rails

Edit 5: For deeper knowledge of OOP check out Sandi Metz’s POODR

Edit 4: The Bible for C Programming: K&R