C Programming

Kim N. King

Mentioned 10

You've never seen a C book like this before: packed with useful information and examples, yet highly readable. Everyone from beginner to expert can profit from reading C Programming: A Modern Approach.

More on Amazon.com

Mentioned in questions and answers.

I just saw a picture today and think I'd appreciate explanations. So here is the picture:

some c code

I found this confusing and wondered if such codes are ever practical. I googled the picture and found another picture in this reddit entry, and here is that picture:

some interesting explanation

So this "reading spirally" is something valid? Is this how C compilers parse?
It'd be great if there are simpler explanations for this weird code.
Apart from all, can these kind of codes be useful? If so, where and when?

There is a question about "spiral rule", but I'm not just asking about how it's applied or how expressions are read with that rule. I'm questioning usage of such expressions and spiral rule's validity as well. Regarding these, some nice answers are already posted.

So this "reading spirally" is something valid?

Applying spiral rule or using cdecl are not valid always. Both fails in some cases. Spiral rule works for many cases, but it is not universal.

To decipher complex declarations remember these two simple rules:

  • Always read declarations from inside out: Start from innermost, if any, parenthesis. Locate the identifier that's being declared, and start deciphering the declaration from there.

  • When there is a choice, always favor [] and () over *: If * precedes the identifier and [] follows it, the identifier represents an array, not a pointer. Likewise, if * precedes the identifier and () follows it, the identifier represents a function, not a pointer. (Parentheses can always be used to override the normal priority of [] and () over *.)

This rule actually involves zigzagging from one side of the identifier to the other.

Now deciphering a simple declaration

int *a[10];

Applying rule:

int *a[10];      "a is"  
     ^  

int *a[10];      "a is an array"  
      ^^^^ 

int *a[10];      "a is an array of pointers"
    ^

int *a[10];      "a is an array of pointers to `int`".  
^^^      

Let's decipher the complex declaration like

void ( *(*f[]) () ) ();  

by applying the above rules:

void ( *(*f[]) () ) ();        "f is"  
          ^  

void ( *(*f[]) () ) ();        "f is an array"  
           ^^ 

void ( *(*f[]) () ) ();        "f is an array of pointers" 
         ^    

void ( *(*f[]) () ) ();        "f is an array of pointers to function"   
               ^^     

void ( *(*f[]) () ) ();        "f is an array of pointers to function returning pointer"
       ^   

void ( *(*f[]) () ) ();        "f is an array of pointers to function returning pointer to function" 
                    ^^    

void ( *(*f[]) () ) ();        "f is an array of pointers to function returning pointer to function returning `void`"  
^^^^

Here is a GIF demonstrating how you go (click on image for larger view):

enter image description here


The rules mentioned here is taken from the book C Programming A Modern Approach by K.N KING.

Lately, I discover more and more that it's good to have extensive knowledge of programming fundamentals. Sadly, I am (one of the many) self-taught PHP developers and have no regrets choosing that path.

However, I still think I should extend my knowledge to some "real" programming languages starting from zero and build up my knowledge from there. I have no intention of changing my career path, but I do think it would be good to think out of the web-development box.

I prefer not taking classes or courses, because I simply do not have the time for this. So:

  • What is the best way to teach myself C step by step, starting from level zero?

  • As my main goal is to learn more programming fundamentals, is C even a good choice for this?

  • If not, what language would be?


Summary so far:

First of all, thanks for all the great responses. These will be quite helpful. Although most people seem to agree that starting off with C is not a bad choice, I have also seen people state that it is probably a better idea to skip C and go with C++ or even C#, since these languages are more current.

My personal opinion is still that it would be good to start from level zero, even if the language itself is not directly contributive to the things I make. I still believe it will indirectly make me a better programmer. But then again, like said, my knowledge of these languages is quite limited, so I'd love to hear your thoughts on the matter aswell.

I have to disagree with the previous two answers who recommend the famous "K&R" guide. I was completely unable to learn anything from that book; I simply gave up after reading the first third of the book about three times. Maybe I'm just dumb.

I suggest, instead, this wonderful book: C Programming: A Modern Approach (disclaimer: amazon link)

I've learned everything I need to know about C from that book, and it covers the history as much as needs to be done, while still keeping a "modern" point of view.

Caveat: I didn't come to C "for C", I passed through it on the way to my eventual goal, Objective-C and Cocoa programming for desktop applications on Apple's Mac OS X. If you really want a very deep knoweldge of C, it may not hurt to get both of the above-mentioned books, and read the K&R guide after reading Modern C

I'm working through a book called C Programming: A Modern Approach and in the first section discussing arrays, the author states:

using a macro to define the length of an array is excellent practice

Then uses the brief example:

#define N 10
...
int a[N];

I understand that it has something to do with being able to go back into the source code of the program and change the value, and making it a macro maybe makes it easier for the programmer, but I'm not certain. Why is this an excellent practice, or is it objective?

It's a good practice because

  • the array size obviously has to be hard-coded
  • but it shouldn't have a magic number injected directly into the source code
  • therefore, a macro is a good way to give it a readable name and remove it from the source

That being said I'm not sure I agree this is the best way. An enum also works and avoids some of the problems with macros (e.g. harder to overwrite and silently compile). And IIRC a const int works as well.

For reference this compiles with cc:

const int s = 1;
int a[s];


int main() {
return 0;
}

Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.4.0
Thread model: posix

I really want to learn C (I'm planning on joining an open source GNOME project). What would be a good tutorial?

The C Programming Language (often referred to as "K & R") is almost universally considered to be the best resource for learning C.

While "The C Programming Language" is certainly a great book and a very good introduction to the C language, it has several drawbacks:

  • It is somewhat dated, the 2nd edition (the last one) covers only C89 which is now 20 years old. While C99 (the current Standard) isn't universally supported, there are a number of features from it that are supported by many implementations and exposure to them is useful.
  • It isn't comprehensive. It doesn't cover many of the standard library functions in any detail and certain intricacies are not explored in depth.
  • The text assumes you are already an experienced programmer and has a very terse style which doesn't work well for everyone.

If you are looking for a more beginner-friendly, comprehensive, or up-to-date book, I would strongly recommend C Programming: A Modern Approach, 2nd Ed. It covers every aspect of the language and the standard library in depth, including C99, and is extremely well-written. While the list price is rather high, it usually isn't difficult to find a copy for around $60 USD.

I’m having some problems learning C and I really have no where else to turn for advice. I come from a list of OOP languages such as JavaScript and mainly Python, so C is a major change and I’m hitting quite a few bumps trying to learn the fundamentals. I initially started with Zed Shaw’s “Learn C the Hard Way”, but he doesn’t really teach anything in the book. Yeah, he makes you write a lot of code and change stuff up, but I’m not learning why the code works and it is just leading to more confusion as the examples build in complication.

The main problems I am having are the difference between variables and pointers (I thought it was pretty distinct until I saw some examples that I’ll be posting below, which completely blurred the line between the two).

For example, I understand that declaring and initializing an int called a and a pointer, p would look like this:

int a;
int *p;

a = 12;
p = &a;

What confuses me is when you declare variables that look like pointers, but aren’t really pointers at all (or are they?). For example:

char *string = "This is a string";
printf("%s\n", string);

What is string when it is defined and initialized? Is it a pointer? And if it is, why don’t you dereference it when printing it in the printf function? There are many examples like this that confuse me.

Another example I came across that made no sense whatsoever:

int i;
scanf("%d", &i);

How does this function update the value of integer i, when the ampersand is supposed to reference the location in memory of the variable, not the value? It gets even more complicated with arrays and structs, which is where I stopped and decided I needed to find some advice.


I honestly feel embarrassed posting such a noob question, but everyone starts somewhere. These fundamentals are something I know I need to be able to understand before moving on, but it is so hard for me to make sense of it when I see examples of code that contradict what I had just learned. I know this is a very general question but I am hoping some of you could either explain these basics or point me in a direction where I can better learn/understand this. Most video tutorials I have come across are too general and same with the text tutorials online, where they tell you how to do something, but don’t explain it, which causes some serious problems down the line.

    char *string = "This is a string";
    printf("%s\n", string);
What is string when it is defined and initialized? Is it a pointer? And if it is, why don’t you dereference it when printing it in the printf function? There are many examples like this that confuse me.

First, a little background:

Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to intialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.

The string literal "This is a string" is an expression of type "17-element array of char" (16 characters plus the 0 terminator). Since it is not the operand of either the sizeof or unary & operators, and since it isn't being used to initialize an array of char, the type of the expression is converted to "pointer to char", and the value of the expression is the address of the first element.

The variable string is declared as type "pointer to char" (char *), and it is initialized with the address of the string literal.

In the printf call, the conversion specifier %s expects its corresponding argument to have type char *; it will print characters starting at the specified address until it sees a 0 terminator. This is why the variable isn't dereferenced in the printf call.

    int i;
    scanf("%d", &i);
How does this function update the value of integer i, when the ampersand is supposed to reference the location in memory of the variable, not the value? It gets even more complicated with arrays and structs, which is where I stopped and decided I needed to find some advice.

C passes all function arguments by value, meaning the formal parameter in the function definition and the actual parameter in the function call are two different objects in memory. Updating the formal parameter has no effect on the actual parameter. For example, imagine a simple swap function, like so:

void swap( int a, int b ) { int tmp = a; a = b; b = tmp; return; }
...
int x = 0, y = 1;
printf( "before swap: x = %d, y = %d\n", x, y );
swap( x, y );
printf( " after swap: x = %d, y = %d\n", x, y );

If you compiled and ran this code, you'd see the same values for x and y in both output statements; a and b are different objects in memory from x and y, and changing the values of a and b has no effect on the values of x and y.

Since we want to modify the values of x and y, we must pass pointers to these variables to the function, like so:

void swap( int *a, int *b ) { int tmp = *a; *a = *b; *b = tmp; return; }
...
int x = 0, y = 1;
printf( "before swap: x = %d, y = %d\n", x, y );
swap( &x, &y );
printf( " after swap: x = %d, y = %d\n", x, y );

Instead of swapping the values of a and b, we swap the values of what a and b point to; the expressions *a and *b refer to the same objects in memory as x and y.

This is why you must pass a pointer to i in the scanf call (the scanf conversion specifier %d expects the corresponding argument to have type int *); you would not be able to update the value of i otherwise.

I haven't been too impressed with "Learn C The Hard Way"; then again, almost all C references have some fatal flaws. Kernighan and Ritchie's The C Programming Language, while pretty long in the tooth (it doesn't cover anything introduced in the last two standard revisions), is still probably the best overall introduction to the language. I've also heard good things about King's C Programming: A Modern Approach. My go-to desktop reference is Harbison & Steele's C: A Reference Manual, although it's exactly what it says it is - a reference manual, and as such not that big on explaining basic concepts.

I read this in the book C programming : A modern approach -

According to C standard statements such as

 c = (b=a+2) - (a=1) ;

causes undefined behavior.

There is no reference to why however. My understanding is this :

  1. All the variables have been modified only once between the sequence points. (So shouldn't be UB)

  2. The order of evaluation of sub expressions is not defined. (But that doesn't mean it invokes undefined behavior, right ?)

What else is causing it to be undefined behavior ?

1 and 2 are perfectly correct. In the case of order of evaluation of operands, it is unspecified for most operators in C. Meaning that either (b=a+2) or (a=1) can get evaluated first, and you cannot know which order that applies for any given case.

In addition, if a variable is modified between two sequence points, any other access to that variable is not allowed, save for calculating what value to store in it.

C99 states this in 6.5 (emphasis mine):

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

So code like a = a+1 is perfectly well-defined, while code like a = a++ leads to undefined behavior.

It all boils down to the "abstract machine" which is the rules determining the execution order of your program. Writing a value to a variable is a side effect and the C standard states that all side effects must have occurred before the next sequence point. Now if you have several side effects related to the same variable, there are no guarantees in which order they will be sequenced in relation to each other, until the next sequence point is reached.

The practical advise to avoid bugs caused by sequencing and order of evaluation, is to keep expressions simple, with as few operators and as few side effects on each line as possible. In the case of your original example, a better way to write the code would be:

b = a + 2;
a = 1;
c = b - a;

The above code cannot be misinterpreted neither by the compiler nor by the human reader.


Just for the record, C11 has different text, but the very same meaning:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

I am learning c, presently. The book I read is C99 based. I want to update my knowledge to C11 after finishing this book, or change resource if there is a major difference. Thus, what I ask is for is an explanation or resource to update my knowledge. I only found this source. Nevertheless, it does not seem to encompass the information I need or not concise.

Thanks in advance. P.S: I want to learn C11 since I think it is the prevalent standard now. If not, please inform me.

Good overviews of C11 standard:
https://en.wikipedia.org/wiki/C11_(C_standard_revision)
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
http://blog.smartbear.com/codereviewer/c11-a-new-c-standard-aiming-at-safer-programming/

The standard includes several changes to the C99 language and library specifications, such as:

  • Alignment specification (_Alignas specifier, _Alignof operator, aligned_alloc function, <stdalign.h> header file)
  • The _Noreturn function specifier and the <stdnoreturn.h> header file
  • Type-generic expressions using the _Generic keyword. For example, the following macro cbrt(x) translates to cbrtl(x), cbrt(x) or cbrtf(x) depending on the type of x:

    #define cbrt(x) _Generic((x), long double: cbrtl, \ default: cbrt, \ float: cbrtf)(x)

  • Multi-threading support (_Thread_local storage-class specifier, <threads.h> header including thread creation/management functions, mutex, condition variable and thread-specific storage functionality, as well as the _Atomic type qualifier and <stdatomic.h> for uninterruptible object access).

  • Improved Unicode support based on the C Unicode Technical Report ISO/IEC TR 19769:2004 (char16_t and char32_t types for storing UTF-16/UTF-32 encoded data, including conversion functions in <uchar.h> and the corresponding u and U string literal prefixes, as well as the u8 prefix for UTF-8 encoded literals).
  • Removal of the gets function, deprecated in the previous C language standard revision, ISO/IEC 9899:1999/Cor.3:2007(E), in favor of a new safe alternative, gets_s.
  • Bounds-checking interfaces (Annex K).
  • Analyzability features (Annex L).
  • More macros for querying the characteristics of floating point types, concerning subnormal floating point numbers and the number of decimal digits the type is able to store.
  • Anonymous structures and unions, useful when unions and structures are nested, e.g. in struct T { int tag; union { float x; int n; }; };.
  • Static assertions, which are evaluated during translation at a later phase than #if and #error, when types are understood by the translator.
  • An exclusive create-and-open mode ("…x" suffix) for open. This behaves like O_CREAT|O_EXCL in POSIX, which is commonly used for lock files.
  • The quick_exit function as a third way to terminate a program, intended to do at least minimal deinitialization if termination with exit fails.
  • Macros for the construction of complex values (partly because real + imaginary*I might not yield the expected value if imaginary is infinite or NaN).

I have referred quite a few books on C, C++, etc. in fact i have even read the Dragon book on Compilers. But my basic doubt remains, is there any link or book i can read which explains a simple C program creating from writing source code in a Editor to Compilation to Linking?

Would appreciate an internet link is provided.

Well... good introductory books are

These cover very well compiling and linking in their first chapters, as well as execution and requirements. These are the books which did the trick for me.

I've got a question about how the scanf function works. In this program:

#include <stdio.h>

int main(void) {

    int x;
    char y;

    printf("Write a number: ");
    scanf("%d", &x);

    printf("Write a character: ");
    scanf(" %c", &y);

    printf("%d", x);
    printf("%c", y);

    return 0;
}

If the user writes a number then hit enter then the scanf function would see from the format string that is should expect a number. When the user taps enter it would not read the new-line character and put it back in the buffer. Then since I am reading a character next I need to have a whitespace in the format string because the scanf function would otherwise take the new-line character and put in the y-variable.

However I am just curious about what happened if the user wrote something like

j344lk4fjk388

Would it put everything back in the buffer? And everything that gets "put-back" in the buffer would it automatically be read by the next scanf function in my program?

I'm reading: C Programming A Modern Approach 2nd Edition

You should always check the return value from scanf() to ensure that all the conversions you expected were successful.

Given the sample input:

j344lk4fjk388

The first scanf() would fail because j cannot be converted to an integer - returning 0 for the number of successful conversions. The second call would succeed, returning 'j' as the character.

If you need the string to be treated as an integer, use fgets() or a relative (perhaps POSIX getline()) to read the string, then strtoul() (or the appropriate relative - strtol(), strtoll(), strtoull(), strtoimax() or strtoumax()), specifying a base of at least 21 to convert the 'j', or 23 to take the 'l' and 'k'.

This is a problem that i encountered while learning to program in c by following this book.

Enter an expression : 1+2.5*3
Output: 10.5

This is what i came up with so far. EDIT

#include<stdio.h>

int main (void)

{
char c;

float f1=0.0f,f2=0.0f;

c = getchar();
while(c != '\n')

{

  if(c!='+' && c!='-' && c!='*' && c!='/')
      {
          if (f1 == 0.0f)
          {
              f1 = c - '0';
              c = getchar();
          }
          else
          {
              f2 = c - '0';
              c = getchar();
          }

      }

 switch (c)
      {
          case '+': c = getchar(); f2 = c - '0' ; f1 = f1+f2; break;
          case '-': c = getchar(); f2 = c - '0' ; f1 = f1-f2; break;
          case '*': c = getchar(); f2 = c - '0' ; f1 = f1*f2; break;
          case '/': c = getchar(); f2 = c - '0' ; f1 = f1/f2; break;
         // case '.':
          default: break;
      }

 c = getchar();

 }
 printf("\n Value of the expression: %.2f", f1);
 return 0;
 }

The code is only implimented in assuming that all of the operands will be one digit number. How do i impliment it for more than one digit/floating point number? What approach should i take to solve this problem.

I have no instructor to consult with(self learning & at chapter 7) and i am stuck at this for hours.So any help will be hugely appreciated.

Thank You

NB

someone mentioned about atoi() ... but I am looking for something else/manual