Expert C Programming

Peter Van der Linden

Mentioned 31

Software -- Programming Languages.

More on Amazon.com

Mentioned in questions and answers.

To follow the example of The Definitive C++ Book Guide and List for C Books here is a wiki post for organization.

A tag search for "C" and "Books" returns no complete book list results as of writing this question. That search is here.

This post is to providing QUALITY books and an approximate skill level. Maybe we can add a short blurb/description about each book that you have personally read / benefited from. Feel free to debate quality, headings, etc.

Reference Style - All Levels

Beginner

Intermediate

Above Intermediate

Uncategorized Additional C Programming Books

C Unleashed : is also a good book. Its not ideal or anything. But for intermediate programmers, its definitely worth practising programs written in this book.

I added The Standard C Library by P.J. Plauger. It contains complete source code to an implementation of the C89 standard library along with extensive discussion. It was very influential to my C programming style. As a library it is much more accessible than, say, STL.

Problem Solving and Program Design in C (6th Edition) is an intermediate level book. If you have other C Advanced books then this is not an ideal book to buy but its definitely worth going through once.

I think the knowledge you're looking for is to be found not in books about C but in books and articles about system design. These are fairly thin on the ground, unfortunately. You might consider

  • Abstraction and Specification in Program Development by Barbara Liskov and John Guttag (not the newer Java-based version by Liskov alone). It is an undergraduate text but has some ideas worth thinking about.

  • Books from the late 1970s and early 1980s by Yourdon and Myers on structured design (one is called Composite/Structured Design.

  • For an example of how to organize a big C project as a bunch of useful libraries, you can't beat C Interfaces and Implementations by Dave Hanson. Basically Hanson took all the code he'd written as part of building Icon and lcc and pulled out the best bits in a form that other people could reuse for their own projects. It's a model of good C programming using modern design techniques (including Liskov's data abstraction).

Beginner: Applications Programming in ANSI C, by Johnsonbaugh & Kalin

Intermediate: Data Structures - An Advanced Approach Using C, by Esakov and Weiss

Beginner

Intermediate

  • Algorithms in C by Robert Sedgewick: gives you a real grasp of implementing algorithms in C; very lucid and clear; you will probably throw away all your algorithms books and keep this one

Expert

I'd like to make an anti-recommendation. Under no circumstances should you read any books by Herbert Schildt. In particular, you should stay away from C: The Complete Reference.

Having read the same books, hopefully I can help with a few more:

And finally a good cookbook-like one from comp.lang.c contributors:

I've recently come to maintain a large amount of scientific calculation-intensive FORTRAN code. I'm having difficulties getting a handle on all of the, say, nuances, of a forty year old language, despite google & two introductory level books. The code is rife with "performance enhancing improvements". Does anyone have any guides or practical advice for de-optimizing FORTRAN into CS 101 levels? Does anyone have knowledge of how FORTRAN code optimization operated? Are there any typical FORTRAN 'gotchas' that might not occur to a Java/C++/.NET raised developer taking over a FORTRAN 77/90 codebase?

Legacy Fortran Soapbox

I helped maintain/improve a legacy Fortran code base for quite a while and for the most part think sixlettervariables is on the money. That advice though, tends to the technical; a tougher row to hoe is in implementing "good practices".

  • Establish a required coding style and coding guidelines.
  • Require a code review (of more than just the coder!) for anything submitted to the code base. (Version control should be tied to this process.)
  • Start building and running unit tests; ditto benchmark or regression tests.

These might sound like obvious things these days, but at the risk of over-generalizing, I claim that most Fortran code shops have an entrenched culture, some started before the term "software engineering" even existed, and that over time what comes to dominate is "Get it done now". (This is not unique to Fortran shops by any means.)

Embracing Gotchas

But what to do with an already existing, grotty old legacy code base? I agree with Joel Spolsky on rewriting, don't. However, in my opinion sixlettervariables does point to the allowable exception: Use software tools to transition to better Fortran constructs. A lot can be caught/corrected by code analyzers (FORCHECK) and code rewriters (plusFORT). If you have to do it by hand, make sure you have a pressing reason. (I wish I had on hand a reference to the number of software bugs that came from fixing software bugs, it is humbling. I think some such statistic is in Expert C Programming.)

Probably the best offense in winning the game of Fortran gotchas is having the best defense: Knowing the language fairly well. To further that end, I recommend ... books!

Fortran Dead Tree Library

I have had only modest success as a "QA nag" over the years, but I have found that education does work, some times inadvertently, and that one of the most influential things is a reference book that someone has on hand. I love and highly recommend

Fortran 90/95 for Scientists and Engineers, by Stephen J. Chapman

The book is even good with Fortran 77 in that it specifically identifies the constructs that shouldn't be used and gives the better alternatives. However, it is actually a textbook and can run out of steam when you really want to know the nitty-gritty of Fortran 95, which is why I recommend

Fortran 90/95 Explained, by Michael Metcalf & John K. Reid

as your go-to reference (sic) for Fortran 95. Be warned that it is not the most lucid writing, but the veil will lift when you really want to get the most out of a new Fortran 95 feature.

For focusing on the issues of going from Fortran 77 to Fortran 90, I enjoyed

Migrating to Fortran 90, by Jim Kerrigan

but the book is now out-of-print. (I just don't understand O'Reilly's use of Safari, why isn't every one of their out-of-print books available?)

Lastly, as to the heir to the wonderful, wonderful classic, Software Tools, I nominate

Classical FORTRAN, by Michael Kupferschmid

This book not only shows what one can do with "only" Fortran 77, but it also talks about some of the more subtle issues that arise (e.g., should or should not one use the EXTERNAL declaration). This book doesn't exactly cover the same space as "Software Tools" but they are two of the three Fortran programming books that I would tag as "fun".... (here's the third).

Miscellaneous Advice that applies to almost every Fortran compiler

  • There is a compiler option to enforce IMPLICIT NONE behavior, which you can use to identify problem routines without modifying them with the IMPLICIT NONE declaration first. This piece of advice won't seem meaningful until after the first time a build bombs because of an IMPLICIT NONE command inserted into a legacy routine. (What? Your code review didn't catch this? ;-)
  • There is a compiler option for array bounds checking, which can be useful when debugging Fortran 77 code.
  • Fortran 90 compilers should be able to compile almost all Fortran 77 code and even older Fortran code. Turn on the reporting options on your Fortran 90 compiler, run your legacy code through it and you will have a decent start on syntax checking. Some commercial Fortran 77 compilers are actually Fortran 90 compilers that are running in Fortran 77 mode, so this might be relatively trivial option twiddling for whatever build scripts you have.

I'm not sure if this is a proper programming question, but it's something that has always bothered me, and I wonder if I'm the only one.

When initially learning C++, I understood the concept of references, but pointers had me confused. Why, you ask? Because of how you declare a pointer.

Consider the following:

void foo(int* bar)
{
}


int main()
{
    int x = 5;
    int* y = NULL;

    y = &x;
    *y = 15;     
    foo(y);

}

The function foo(int*) takes an int pointer as parameter. Since I've declared y as int pointer, I can pass y to foo, but when first learning C++ I associated the * symbol with dereferencing, as such I figured a dereferenced int needed to be passed. I would try to pass *y into foo, which obviously doesn't work.

Wouldn't it have been easier to have a separate operator for declaring a pointer? (or for dereferencing). For example:

void test(int@ x)
{
}

Page 65 of Expert C Programming: Deep C Secrets includes the following: And then, there is the C philosophy that the declaration of an object should look like its use.

Page 216 of The C Programming Language, 2nd edition (aka K&R) includes: A declarator is read as an assertion that when its identifier appears in an expression of the same form as the declarator, it yields an object of the specified type.

I prefer the way van der Linden puts it.

For OOP languages, there are many books describing how to design software, and design patterns are mainly for OOP languages.

I am wondering whether there are any books/good articles teaching how to use C in a big project, like it is a good practice to use static functions when this function is only used in a single file.

You must read Expert C Programming by Peter van der Linden.

alt text

Code Complete 1st Ed by Steve McConell is more oriented towards C, that may be worth a look as well. At any rate his books are great reading for any professional programmer.

G'day,

While heavily focused on C++, John Lakos's excellent book "Large-Scale C++ Software Design" has a lot of information that is very relevant to the design of software written in C.

Edit: Oooh. After seeing @Jackson's suggestion for the excellent "The Practice of Programming" I'd also highly recommend Eric Raymond's excellent book "The Art of UNIX Programming.". Thanks for the reminder @Jackson.

HTH

cheers,

  1. C FAQ
  2. K & R
  3. Linux kernel source code

If the following assignment is valid:

int a[2] = {1,2};
int* b = a;

then what is wrong with this:

int a[2][2]={1,2,3,4};
int** b = a;

C++ gives an error that it can't convert int[][] to int**. What is difference between the two types if int[] is the same as int*?

Take it easy. It is only a compiler error. Arrays are pretty tricky. Here is the rule:

The value of a variable of type array decays to the address of element zero of this array

Your first snippet looks like:

int a[2] = {1,2};

So according to the rule if a is in the right hand side of a assignment then it decays to address of the element zero and that is why it has type int *. This brings you to

int *b = a;

In the second snippet what you really have is an array of arrays. (By the way, to make it explicit I've changed your code a bit.)

int a[2][2]={{1,2},{3,4}};

This time a will decay to the pointer to an array of two integers! So if you would want to assign a to something, you would need this something to have the same type.

int (*b)[2] = a; //Huh!

(This syntax maybe a bit stunning to you, but just think for a moment that we have written int *b[2]; Got the point? b would be an array of pointers to integers! Not really what we wanted...)

You could stop reading here, but you could also move on, because I have not told you all the truth. The rule I mentioned has three exceptions...

The value of the array will not decay to the address of the element zero if

  1. array is operand of sizeof
  2. array is operand of &
  3. array is a literal string initializer for a character array

Let's explain these exceptions in more detail and with examples:

int a[2];

int *pi = a ; /* the same as pi = &a[0]; */

printf("%d\n", sizeof(a)); /* size of the array, not of a pointer is printed! */

int (*pi2)[2] = &a; /* address of the array itself is taken (not the address of a pointer) */

And finally

char a[] = "Hello world ";

Here not a pointer to "Hello world" is copied, but the whole string is copied and a points to this copy.

There is really a lot of information and it is really difficult to understand everything at once, so take your time. I recommend you to read K&R on this topic and afterwards this excellent book.

according to MSDN the typedef syntax is:

typedef type-declaration synonym;

Very easy:

typedef int MY_INT;

But how the heck does the member-function-pointer typedefs comply to this rule?

typedef int (MyClass::*MyTypedef)( int);

100% confusion – the synonym (MyTypedef) is in the middle?

Can someone please explain what the logical steps are to get from the very easy to understand syntax format of MSDN to the reverse/random/front/last/mixed syntax thing of aboves typedef?

*edit thanks for all the fast answers (and the beautification of my post) :)

I once read a nice explanation (but it's from Expect C Programming so I ymmv):

In fact, a typedef has exactly the same format as a variable declaration, only with this extra keyword to tip you off.

Since a typedef looks exactly like a variable declaration, it is read exactly like one. Instead of the declaration saying "this name refers to a variable of the stated type," the typedef keyword doesn't create a variable, but causes the declaration to say "this name is a synonym for the stated type."

So there you have it. Imagine you're declaring a variable, stick typedef before it and voila, you have a new type. MSDN explanations are a mixed bag: I've read really god ones and downright bad ones.

In spite of having read K&R, and having even taught C classes, I find myself embarrassingly unable to fully understand what one might call "modern" C.

There seems to be many unwritten conventions in modern programming that, as far as I know, aren't documented anywhere.

Take, for example, the SQLite source code. In it I find for instance:

 SQLITE_API int sqlite3_close(sqlite3 *);

What does SQLITE_API stand for? How is this even syntactically correct?

Or this:

#ifndef _SQLITE3_H_
#define _SQLITE3_H_

Is there an accepted convention somewhere on when to prefix macros with underscores? Sometimes I see macros prefixed with two underscores.

Or what about the use of fixed-size types, such as uint32 and so forth. When should one use this practice, and when not? What about the new-ish bool type, when should it be preferred over simple ints?

These are some of the questions I pose myself when I read other people's source code. Is there a reference somewhere that might help me answer these questions?

Expert C Programming Is a great follow up to K&R. Don't be put off by the title. It is a very accessible book if you know the basics of C. It covers a lot of real world code situations which K&R is pretty short on.

With that said there is really no substitute for reading and writing code. Most of the modern conventions are not really standards and often are adhered to differently in different code bases. They are just common solutions to the problems and limitations everyone faces writing in the language. The most important thing in my opinion is to understand what those problems and limitations are.

#include <stdio.h>

int main()
{
    int a=8,b=9,c;
    c=a+++b;
    printf("%d%d%d\n",a,b,c);
    return 0;
}

The program above outputs a=9 b=9 and c=17. In a+++b why is the compiler takes a++ and then adds with b. Why is it not taking a + and ++b? Is there a specific name for this a+++b. Please help me to understand.

I like the explanation from Expert C Programming:

The ANSI standard specifies a convention that has come to be known as the maximal munch strategy. Maximal munch says that if there's more than one possibility for the next token, the compiler will prefer to bite off the one involving the longest sequence of characters. So the example will be parsed

c = a++ + b;

After The C Programming Language by Brian Kernighan and Dennis Ritchie, some of the books most favoured by beginners turn out to be ones best avoided, such as anything by Herb Schildt or even the O'Reilly Practical C Programming, and there doesn't seem to be much alternative to these. Otherwise most of the material available is about C++.

Besides K&R and the excellent C: A Reference Manual which I have already, what other books are the best to use for learning to code in C, (plain C89 and not C++), without learning bad practices along the way?

Peter van der Linden's Expert C Programming: Deep C Secrets

K&R essentially covers everything you need to know about C, and even implements a few data structures that are commonly used. If you're using *nix and want to learn how to take advantage of the operating system, Advanced Programming in the UNIX Environment, Third Edition is a good reference/guide to common uses such as reading a file, creating threads, etc. Sample code is in C.

A great book to learn C is: C BY DISSECTION The Essentials of C Programming by Al Kelley & Ira Pohl

Very easy to read wth lots of great programming examples.

I like Pointers on C by Kenneth A. Reek. I won't do so far as to say it's better than K&R but I certainly found it more friendly and easier to learn from. I started with K&R, but didn't really get a hang of C until I picked up this book.

Edit: I also just found out that the price of this book has skyrocketed since I bought it. So while my recommendation still stands as such, I cannot really recommend it at the current asking price. So if you can find a used copy or a copy at a library then it's worth getting, but at its current price there are other books that are basically just as good for a lot less money.

Expert C Programming is book I consider worth at least looking through once you've gotten the hang of C, although I'm hesitant to outright recommend it. On the plus side it contains a number of good tips and tricks and some very useful advice. On the minus side those tricks and pieces of advice are badly organize, buried among not so useful advice and half the book seems filled with lame jokes, asides and irrelevant (but occasionally amusing) stories. So I'd borrow it from the library, but not pay money for it.

But as you no doubt realize, you'll never really learn C until you write C.

Beginning C by Ivor Horton (3rd edition) from APress is a great introductory book on C programming. This book is very thorough and is not a reference book but a good tutorial from start to end on everything in the C language.

Beginning C by Ivor Horton (3rd Edition)

The best textbook on C I have is C: A Software Engineering Approach by Peter A. Darnell and Philip E. Margolis. While it is (undeservedly) not as famous as other books, I found it very readable and it handles all the details K&R skips over.

It has two disadvantages though:

  1. It is from 1996, so it does not cover C99. (This should be fine with you since you are interested in C89.)
  2. It is quite expensive.

Edit: Another book of interest is C Programming FAQs by Steve Summit. While I don't have this book in print, the accompanying web site helped me a lot in understanding the less obvious features of C.

I am currently using gcc to compile and I need to use <math.h>. Problem is that it won't recognize the library. I have also tried -lm and nothing. The function I tried to use was ceil() and I get the following error:

: undefined reference to `ceil'
collect2: ld returned 1 exit status

I am using the latest Ubuntu and math.h is there. I tried to use -lm in a different computer and it work perfectly.

Does anyone know how to solve this problem?


I did include <math.h>. Also, the command I used was:

gcc -lm -o fb file.c

Don't have enough reputation to comment on @Jonathan Leffler's answer. Just wanted to mention that Peter van der Linden's book Expert C Programming has a good treatment on this subject in chapter 5 Thinking of Linking.

Archives (static libraries) are acted upon differently than are shared objects (dynamic libraries). With dynamic libraries, all the library symbols go into the virtual address space of the output file, and all the symbols are available to all the other files in the link. In contrast, static linking only looks through the archive for the undefined symbols presently known to the loader at the time the archive is processed.

If you specify the math library (which is usually a static one) before your object files, then the linker won't add any symbols.

I come from a PHP based background and my new years resolution was to listen to Joel and learn C.

I am using a Windows based PC and I don't mind programming that's focused a little on the Windows side though I will be starting with console applications.

  • What compiler could I use and why?
  • What IDE could I use and why?
  • What other tools are useful for a beginner C programmer?
  • Are there free online guides?

I tried to look for SO questions but the C tag has no good questions on the Hot list but if you know of some good SO questions that are related to this one, don't hesitate to add it here below.

SO Posts

After K&R (aka The Bible in my CS class), I would recommend this book: link text It covers some of the tricky parts of C and is very well written. And you even get a certificate of completion. How could you beat that!

I'll answer your questions in order:

  • What compiler could I use and why? - Generally, gcc on the Unix world, and since you said you don't mind Windows, the latest version of MSVC (2008). though it doesn't support C99. (Remember to change the project settings to compile as C.)
  • What IDE could I use and why? - I've heard good things about Eclipse, but I never got much into it since I'm on Windows, and gcc options for Windows are... not stellar. MSVC 2008 is good, but Intellisense doesn't quite live up to C#, though it isn't as important in C as in C++. I've heard they're fixing this for 2010.
  • What other tools are useful for a beginner C programmer? - Turn up your warning level to the maximium supported by the compiler. (To a reasonable standard.) This will help you mantain good coding practices.
  • Are there free online guides? - Yes. I don't know of any very good ones though. Get K&R 2nd Ed. It's an awesome book, and short too, by the creators of the language.

And another bit of advice: Try to stick to, and learn, standard ANSI C first, stay away from proprietary extensions.

Studying the K&R book in C I had a few questions regarding complicated pointer declarations and pointer-array relationships.

1) What exactly is the difference between

char amessage[] = "this is a string";

and

char *pmessage
pmessage = "this is a string"

and when would you use one or the other?

From my understanding the first one allocates some amount of memory according to the size of the string, and then stores the chars in the memory. Then when you access amessage[] you just directly access whatever char you're looking for. For the second one you also allocate memory except you just access the data through a pointer whenever you need it. Is this the correct way of looking at it?

2) The book says that arrays when passed into functions are treated as if you gave the pointer to the first index of the array and thus you manipulate the array through manipulating the pointer even though you can still do syntax like a[i]. Is this true if you just created an array somewhere and want to access it or is it only true if you pass in an array into a function? For example:

char amessage[]= "hi";
char x = *(amessage + 1); // can I do this?

3) The book says the use of static is great in this particular function:

/* month_name:  return name of n-th month */
char *month_name(int n)
{
    static char *name[] = {
       "Illegal month",
       "January", "February", "March",
       "April", "May", "June",
       "July", "August", "September",
       "October", "November", "December"
   };
   return (n < 1 || n > 12) ? name[0] : name[n];
}

I don't understand why exactly this is a good use of static. Is it because the char *name[] would get deleted after function return if it is not static (because its a local variable)? Then does that mean in c you can't do stuff like:

void testFunction(){
    int x = 1;
    return x; 
}

Without x being deleted before you use the return value? (Sorry I guess this might not be a pointer question but it was in the pointer chapter).

4) There are some complicated declaration like

char (*(*x())[])()

I'm really confused as to what is going on. So the x() part means a function x that returns a pointer? But what kind of pointer does it return its just a "" without like int or void or w/e. Or does that mean a pointer to a function (but I thought that would be like (*x)())? And then after you add brackets (because I assume brackets have the next precedence)...what is that? An array of functions?

This kind of ties to my confusion with function pointers. If you have something like

int (*func)() 

That means a pointer to a function that returns an int, and the name of that pointer is func, but what does it mean when its like int (*x[3])(). I don't understand how you can replace the pointer name with an array.

Thanks for any help!

Kevin

1) What exactly is the difference between

char amessage[] = "this is a string";

and

char *pmessage
pmessage = "this is a string"

and when would you use one or the other?

amessage will always refer to the memory holding this is a string\0. You cannot change the address it refers to. pmessage can be updated to point to any character in memory, whether or not it is part of a string. If you assign to pmessage, you might lose your only reference to this is a string\0. (It depends if you made references anywhere else.)

I would use char amessage[] if I intended to modify the contents of amessage[] in place. You cannot modify the memory that pmessage points to. Try this little program; comment out amessage[0]='H' and pmessage[0]='H'; one at a time and see that pmessage[0]='H'; causes a segmentation violation:

#include <stdio.h>

int main(int argc, char* argv[]) {
    char amessage[]="howdy";
    char *pmessage="hello";
    amessage[0]='H';
    pmessage[0]='H';
    printf("amessage %s\n", amessage);
    printf("pmessage %s\n", pmessage);
    return 0;
}

Modifying a string that was hard-coded in the program is relatively rare; char *foo = "literal"; is probably more common, and the immutability of the string might be one reason why.

2) The book says that arrays when passed into functions are treated as if you gave the pointer to the first index of the array and thus you manipulate the array through manipulating the pointer even though you can still do syntax like a[i]. Is this true if you just created an array somewhere and want to access it or is it only true if you pass in an array into a function? For example:

char amessage[]= "hi";
char x = *(amessage + 1); // can I do this?

You can do that, however it is pretty unusual:

$ cat refer.c
#include <stdio.h>

int main(int argc, char* argv[]) {
    char amessage[]="howdy";
    char x = *(amessage+1);
    printf("x: %c\n", x);
    return 0;
}

$ ./refer
x: o
$ 

At least, I have never seen a "production" program that did this with character strings. (And I'm having trouble thinking of a program that used pointer arithmetic rather than array subscripting on arrays of other types.)

3) The book says the use of static is great in this particular function:

/* month_name:  return name of n-th month */
char *month_name(int n)
{
    static char *name[] = {
       "Illegal month",
       "January", "February", "March",
       "April", "May", "June",
       "July", "August", "September",
       "October", "November", "December"
   };
   return (n < 1 || n > 12) ? name[0] : name[n];
}

I don't understand why exactly this is a good use of static. Is it because the char *name[] would get deleted after function return if it is not static (because its a local variable)? Then does that mean in c you can't do stuff like:

void testFunction(){
    int x = 1;
    return x; 
}

Without x being deleted before you use the return value? (Sorry I guess this might not be a pointer question but it was in the pointer chapter).

In this specific case, I believe the static is needless; at least GCC is able to determine that the strings are not modified and stores them in the .rodata read-only data segment. However, that might be an optimization with string literals. Your example with another primitive data type (int) also works fine because C passes everything by value both on function calls and function returns. However, if you're returning a pointer to an object allocated on the stack then the static is absolutely necessary, because it determines where in memory the object lives:

$ cat stackarray.c ; make stackarray
#include <stdio.h>

struct foo { int x; };

struct foo *bar() {
    struct foo array[2];
    array[0].x=1;
    array[1].x=2;
    return &array[1];
}

int main(int argc, char* argv[]) {
    struct foo* fp;
    fp = bar();

    printf("foo.x: %d\n", fp->x);
    return 0;
}

cc     stackarray.c   -o stackarray
stackarray.c: In function ‘bar’:
stackarray.c:9:2: warning: function returns address of local variable

If you change the storage duration of array to static, then the address that is being returned is not automatically allocated, and will continue to work even after the function has returned:

$ cat staticstackarray.c ; make staticstackarray ; ./staticstackarray
#include <stdio.h>

struct foo { int x; };

struct foo *bar() {
    static struct foo array[2];
    array[0].x=1;
    array[1].x=2;
    return &array[1];
}

int main(int argc, char* argv[]) {
    struct foo* fp;
    fp = bar();

    printf("foo.x: %d\n", fp->x);
    return 0;
}

cc     staticstackarray.c   -o staticstackarray
foo.x: 2

You can see where the memory allocation changes between stackarray and staticstackarray:

$ readelf -S stackarray | grep -A 3 '\.data'
  [24] .data             PROGBITS         0000000000601010  00001010
       0000000000000010  0000000000000000  WA       0     0     8
  [25] .bss              NOBITS           0000000000601020  00001020
       0000000000000010  0000000000000000  WA       0     0     8
$ readelf -S staticstackarray | grep -A 3 '\.data'
  [24] .data             PROGBITS         0000000000601010  00001010
       0000000000000010  0000000000000000  WA       0     0     8
  [25] .bss              NOBITS           0000000000601020  00001020
       0000000000000018  0000000000000000  WA       0     0     8

The .bss section in the version without static is 8 bytes smaller than the .bss section in the version with static. Those 8 bytes in the .bss section provide the persistent address that is returned.

So you can see that the case with strings didn't really make a difference -- at least GCC doesn't care -- but pointers to other types of objects, the static makes all the difference in the world.

However, most functions that return data in function-local-static storage have fallen out of favor. strtok(3), for example, extracts tokens from a string, and if subsequent calls to strtok(3) include NULL as the first argument to indicate that the function should re-use the string passed in the first call. This is neat, but means a program can never tokenize two separate strings simultaneously, and multiple-threaded programs cannot reliably use this routine. So a reentrant version is available, strtok_r(3), that takes an additional argument to store information between calls. man -k _r will show a surprising number of functions that have reentrant versions available, and the primary change is reducing static use in functions.

4) There are some complicated declaration like

char (*(*x())[])()

I'm really confused as to what is going on. So the x() part means a function x that returns a pointer? But what kind of pointer does it return its just a "" without like int or void or w/e. Or does that mean a pointer to a function (but I thought that would be like (*x)())? And then after you add brackets (because I assume brackets have the next precedence)...what is that? An array of functions?

This kind of ties to my confusion with function pointers. If you have something like

int (*func)() 

That means a pointer to a function that returns an int, and the name of that pointer is func, but what does it mean when its like int (*x[3])(). I don't understand how you can replace the pointer name with an array.

First, don't panic. You'll almost never need anything this complicated. Sometimes it is very handy to have a table of function pointers and call the next one based on a state transition diagram. Sometimes you're installing signal handlers with sigaction(2). You'll need slightly complicated function pointers then. However, if you use cdecl(1) to decipher what you need, it'll make sense:

       struct sigaction {
           void     (*sa_handler)(int);
           void     (*sa_sigaction)(int, siginfo_t *, void *);
           sigset_t   sa_mask;
           int        sa_flags;
           void     (*sa_restorer)(void);
       };

cdecl(1) only understands a subset of C native types, so replace siginfo_t with void and you can see roughly what is required:

$ cdecl
Type `help' or `?' for help
cdecl> explain void     (*sa_sigaction)(int, void *, void *);
declare sa_sigaction as pointer to function
    (int, pointer to void, pointer to void) returning void

Expert C Programming: Deep C Secrets has an excellent chapter devoted to understanding more complicated declarations, and even includes a version of cdecl, in case you wish to extend it to include more types and typedef handling. It's well worth reading.

I'm trying to figure out what the following code in C does?

((void(*)())buf)();

where 'buf' is a char array.

You might find "expert c programming" a good read - unpacking this kind of thing is in one of the chapters, if I remember right. It's a long time since I read it, but I remember thinking it was worth the effort at the time. http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298

So I have some code that looks like this:

int a[10];
a = arrayGen(a,9);

and the arrayGen function looks like this:

int* arrayGen(int arrAddr[], int maxNum)
{
    int counter=0;
    while(arrAddr[counter] != '\0') {
        arrAddr[counter] = gen(maxNum);
        counter++;
    }
    return arrAddr;
}

Right now the compilier tells me "warning: passing argument 1 of ‘arrayGen’ makes integer from pointer without a cast"

My thinking is that I pass 'a', a pointer to a[0], then since the array is already created I can just fill in values for a[n] until I a[n] == '\0'. I think my error is that arrayGen is written to take in an array, not a pointer to one. If that's true I'm not sure how to proceed, do I write values to addresses until the contents of one address is '\0'?

I'm not sure what you are trying to do but the assignment of a pointer value to an array is what's bothering the compiler as mentioned by Charlie. I'm curious about checking against the NUL character constant '\0'. Your sample array is uninitialized memory so the comparison in arrayGen isn't going to do what you want it to do.

The parameter list that you are using ends up being identical to:

int* arrayGen(int *arrAddr, int maxNum)

for most purposes. The actual statement in the standard is:

A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

If you really want to force the caller to use an array, then use the following syntax:

void accepts_pointer_to_array (int (*ary)[10]) {
    int i;
    for (i=0; i<10; ++i) {
        (*ary)[i] = 0; /* note the funky syntax is necessary */
    }
}

void some_caller (void) {
    int ary1[10];
    int ary2[20];
    int *ptr = &ary1[0];
    accepts_pointer_to_array(&ary1); /* passing address is necessary */
    accepts_pointer_to_array(&ary2); /* fails */
    accepts_pointer_to_array(ptr);   /* also fails */
}

Your compiler should complain if you call it with anything that isn't a pointer to an array of 10 integers. I can honestly say though that I have never seen this one anywhere outside of various books (The C Book, Expert C Programming)... at least not in C programming. In C++, however, I have had reason to use this syntax in exactly one case:

template <typename T, std::size_t N>
std::size_t array_size (T (&ary)[N]) {
    return N;
}

Your mileage may vary though. If you really want to dig into stuff like this, I can't recommend Expert C Programming highly enough. You can also find The C Book online at gbdirect.

I am using only C for 5 years. So I am sure that I know C grammar, but I have no idea how to advance programming skills.

There are many books for modern languages (such as C++, Java) to study programming skills like the refactoring or pattern, software architecture. But no book is written with C language. The book author say that his/her book is not language-dependent, but I don't think so.

How can I advance my programming skills? I have to study modern language and read the books? Are there books about software design or programming skill written with C?

One excellent book on "advanced" C programming is Peter van der Linden's Expert C Programming.

You even get an appendix with funny interview stories :)!

A really good book I just found (through Stack Overflow) on C is Expert C, which delves into real detail on the C language. That being said, if you're interested in learning general programming techniques (rather than just advanced C), I'd recommend learning another language, such as Python or Java, since it's much easier to grasp concepts such as algorithms, data structures, and design patterns in higher-level languages.

Are

int (*x)[10];

and

int x[10];

equivalent?

According to the "Clockwise Spiral" rule, they parse to different C declarations.

For the click-weary:

The ``Clockwise/Spiral Rule'' By David Anderson

There is a technique known as the ``Clockwise/Spiral Rule'' which enables any C programmer to parse in their head any C declaration!

There are three simple steps to follow:

   1. Starting with the unknown element, move in a spiral/clockwise direction; 
          when ecountering the following elements replace them with the 
          corresponding english statements:

      [X] or []
          => Array X size of... or Array undefined size of... 
      (type1, type2)
          => function passing type1 and type2 returning... 
      *
          => pointer(s) to... 

   2. Keep doing this in a spiral/clockwise direction until all tokens have been covered.

   3. Always resolve anything in parenthesis first! 

I tend to follow The Precedence Rule for Understanding C Declarations which is given very nicely in the book Expert C Programming - Deep C Secrets by Peter van der Linden

A - Declarations are read by starting with the name and then reading in 
precedence order.

B - The precedence, from high to low, is:
        B.1 parentheses grouping together parts of a declaration
        B.2 the postfix operators:
        parentheses () indicating a function, and
        square brackets [] indicating an array.
        B.3 the prefix operator: the asterisk denoting "pointer to".

C If a const and/or volatile keyword is next to a type specifier (e.g. int, 
        long, etc.) it applies to the type specifier. 
        Otherwise the const and/or volatile keyword 
        applies to the pointer asterisk on its immediate left.

As I understand pointers contain the address of data at another memory location?
When an app is running how is the location of pointers kept track of? Why bother keeping track of the pointer, why not just directly keep track of address the pointer holds?

Additionally if I have the following code:

NSString *string = @"hello";
string = @"bye";

I am changing the value stored in the pointer named string (is it the pointer that is named string or the NSString object?) to the address of the new string ("bye"), right?
So how would I go about changing directly the object stored at the address held by the pointer?

(Also what is the correct terminology to use where I have used "keep track of"?)

Thanks

When an app is running how is the location of pointers kept track of?

Pointers are stored as any other variable; they typically take the same size as an unsigned long, but this is by no means guaranteed, just to give you an idea of how they are implemented. Compilers are free to do a huge variety of optimizations, so the pointers may be stored in memory, they may be stored in registers, or they may exist only as hypothetical entities if they are optimized away.

Consider the following code:

void foo(void) {
    char *c;
    char buf[100];
    for (c=buf; c < buf+100; c++ {
        c = '0';
    }
}

In this case, the variable c is being used to write an ASCII 0 character to every character in the buf array. c may exist only in a register, because it does not live beyond this function. (There are better ways of writing this code.)

Consider the following code:

struct foo {
    char name[10];
    struct foo *next;
}

The member next in this case is a pointer to further struct foo objects -- say, a linked list of these things. These pointers must be stored in memory, because they are part of the contract of these objects -- they have to be there. There is no way around these pointers, either -- the objects they point to can be replaced with other objects on the programmer's whim. And, since the number of these objects is determined entirely at runtime, the compiler can't just keep track of the addresses in its symbol tables, as it would for stack-allocated variables.

So how would I go about changing directly the object stored at the address held by the pointer?

This is complicated by your example's use of "foo" strings in the code. These are saved in read-only memory in the process address space, so you cannot modify them. (Surprise!) If you initialize the strings with another method, you can modify the data via the pointer:

char *c = malloc(10);
strcpy(c, "hello");
c[0] = 'H';
printf("c: %s\n", c);

This will overwrite the h with H in the allocated space available via the c pointer. Accessing pointers as if they were arrays is the same re-writing the pointer access like this:

c[0] = 'f';
c+0 = 'f';

And, in fact, array accesses are pretty similar -- the name of the array is the same as a pointer to its first element.

It's a little complicated; the book Expert C Programming covers pointers in astonishing detail and is well worth the money.

I have read this implementation of glyphs in the Expert C Programming by Peter Van Der Linden. He states this method to draw a glyph pattern. This question is strictly restricted to the context of C programming.

static unsigned short stopwatch[] = {
    0x07C6,
    0x1FF7,
    0x383B,
    0x600C,
    0x600C,
    0xC006,
    0xC006,
    0xDF06,
    0xC106,
    0xC106,
    0x610C,
    0x610C,
    0x3838,
    0x1FF0,
    0x07C0,
    0x0000
};

and then define

#define X )*2+1
#define _ )*2
#define s ((((((((((((((((0

for drawing glyphs 16-bits wide.

Then the above array is converted to a glyph pattern of a StopWatch.

How do we draw those glyphs on the screen without using the graphics? Is there any method to draw the glyph patterns of other objects like outline of maps, face of a person roughly without having to plot each of the pixels, and without using the regular C graphics?

Are there any algorithms that were followed?

There is just a few lines of code missing:

int main()
{
    int i,j;
    for ( i=0;stopwatch[i];i++ )
    {
        for ( j=1<<16;j;j>>=1 ) printf("%c",stopwatch[i]&j?'o':' ');
        printf("\n");
    }
}

voila, stopwatch:

      ooooo   oo 
    ooooooooo ooo
   ooo     ooo oo
  oo         oo  
  oo         oo  
 oo           oo 
 oo           oo 
 oo ooooo     oo 
 oo     o     oo 
 oo     o     oo 
  oo    o    oo  
  oo    o    oo  
   ooo     ooo   
    ooooooooo    
      ooooo      

The define statements are a shorthand to arrive at the magic values in that list:

$ gcc -E -x c -
#define X )*2+1
#define _ )*2
#define s ((((((((((((((((0 

s _ _ _ _ _ _ X X X X _ _ _ _ _ _

// will be preprocessed to:
^D

((((((((((((((((0 )*2 )*2 )*2 )*2 )*2 )*2 )*2+1 )*2+1 )*2+1 )*2+1 )*2 )*2 )*2 )*2 )*2 )*2

That last blurb is an expression which leads to some value (in this case 960 or 0x03c0) you could use in that "stopwatch" list.

In the following code

 int x[2][3] = {{1,2,3},{4,5,6}};
 int* y1 = (int*)x[1];
 int* y2 = (int*)&x[1];

 int i;
 for(i=0; i < 3 ; i++)
 {
  printf("%i %i\n",y1[i],y2[i]);
}

why do y1 and y2 point to the same data?

I would think that x[1] is a pointer to the second row of data, so y1 should be the correct way to access it. The expression &x[1] is getting the address of the pointer to the second row of data, so why does y2 even work?

Well, x[1] is an array, not a pointer. The funky detail here is that address of the array is the array itself :), so to say, as in:

int a[10] = {0};
assert(( int* )a == ( int* )&a);

Edit 0:

To answer your question in the comment: A line like int a[XXX]; reserves a chunk of memory of size sizeof( int ) * XXX. Every time you use a to access that memory, a is replaced with the address of the first element. The compiler knows that address (or at least the offset of the first element from the data segment or from the stack frame). This eliminates the need for storing that address in a temporary, and then dereferencing that temporary to get to the memory itself. Compiler forms the expression with (almost) direct value of the address. Thus a here in a sense has no location to take address of, so to preserve the semantics the &a is short-circuited to just a.

On the other hand, if you pass a as a function argument it's decayed to a pointer.

All fun stuff. Get yourself this book to see more: "Expert C Programming Deep C Secrets"

This is one of the exam questions and the goal is to determine what the program will write. I am really confused about what int (*f[])(int*) = {f1, f2, f2, f1 }; is. I taught that it may be an array whose elements are results of the functions in the brackets and those results are addresses that point on to an int.

Could you maybe explain it to me please?

And as well, what parameter does the function f[i++] get in

for (i=0; i<2; a += fx(f[i++], a));

Problem:

int f2(int *p) { return *p-- + 2; }

int f1(int *q) { return ++*q; }

int fx(int (*pf)(int*), int q) {
    int t = q;
    while ((t = pf(&q)) % 2) q+=2;
    return t;
}

#include <stdio.h>

void main() {
    int a = 4, b = 3, *p = &b, i;
    int (*f[])(int*) = {f1, f2, f2, f1 };

    for (i=0; i<2; a += **fx(f[i++]**, a));
    printf("%d", a + *p);
}

It declares f as an array of pointers to function that returns int and take int * as an argument.

There is a precedence rule for understanding complex declarations which is discussed in the book Expert C Programming: Deep C Secrets:

The Precedence Rule for Understanding C Declarations

  • A. Declarations are read by starting with the name and then reading in precedence order.

  • B. The precedence, from high to low, is:

  • B.1. parentheses grouping together parts of a declaration

  • B.2. the postfix operators:
    parentheses () indicating a function, and
    square brackets [] indicating an array.

  • B.3. the prefix operator:
    the asterisk denoting "pointer to".

  • C. If a const and/or volatile keyword is next to a type specifier (e.g. int, long, etc.) it applies to the type specifier. Otherwise the const and/or volatile keyword applies to the pointer asterisk on its immediate left.

Therefore, it goes like:

      f                          -- f (A)
     f[]                         -- is an array (B.1)
    *f[]                         -- of pointers to (B.3)
   (*f[])( )                     -- function (B.2)
 (*f[])( int * )                 -- that expects a pointer to an int as an argument
int (*f[])( int* )               -- and return an int     

I would suggest to avoid spiral rule as it fails in some cases, for example in case of int* a[10][15];.

Possible Duplicates:
What is the best approach for a Java developer to learn C++

How would you go about learning C++ if you were "Stuck in your ways" with newer languages like Java or C#?

I've been working as a developer for 3 years, I've got both a Bachellors and a masters in computing science from a Reputable UK University...

I've written millions of lines of C# thousands of lines of Java and a few hundred lines of C...

But I don't know C++, I feel a little like I've cheated the profession by not knowing a what I think is a key language. I've written Code in C++ files, mainly for bug fixes, but it was really just C in disguise.

What is the best way to go about learning C++, if you are more used to the nice abstractions that higher level languages give you to get away from the nitty grittyness of C++.

Has anyone on SO gone from being an experienced Java, C# (or some other language) developor to a C++ programmer? if so how did you do it, was it difficult and do you have any pointers?

Since you already have some C programming skills, I would suggest Expert C Programming: Deep C Secrets by Peter van der Linden. It has a great section on C++ to get you from C to C++. That should get you running with C++ syntax. Of course you can go straight to the Stroustrup if you feel more hungry...

Get a good C/C++ compiler and get working...

Context:

I programmed in C on and off for about 2 years before discovering that a[i] is just syntax sugar for *(a + i) and was therefore equivalent to *(i + a) and i[a]. My reality was turned upside down and many a "AHA!" revelationary moment followed in the following few days of study and reading up ("So THAT's why arrays are always passed by reference!" etc). Since then I've internalised the pointer/array equivalence and held it close to my heart, so imagine what a rude shock it was when I stumbled upon this thing called "Array decay". Here's the typical example:

Code:

#include <stdio.h>

int Length(int*);

int main () {
  int arr[100];
  printf("Length of array: %d\n",(int)(sizeof(arr)/sizeof(arr[0])));
  printf("Length of array: %d\n",Length(arr));
  return 0;
}

int Length(int arr[]) {
   return sizeof(arr)/sizeof(arr[0]);
}

Result:

Length of array: 100
Length of array: 2

Question:

So it turns out that C has some recognition of arrays after all! In main where the array was declared, the program is able to correctly report on it's size. Now I'm wondering just how much of array syntax is only syntax sugar for pointer operations (previously I had assumed: All of it). C actually does have arrays, what are their limitations? The example shows that it is possible to get their length as long as you're in the same function, what other cool stuff can you do? How far can you go before this decay thing kicks in?

Saying that arrays and pointers are "equivalent" means neither that they are identical nor even interchangeable. What it means is that it's pointer arithmetic and array indexing that are equivalent in C, pointers and arrays are different.

A reference to an object of type array-of-T which appears in an expression decays into a pointer to its first element; the type of the resultant pointer is pointer-to-T. That is, whenever an array appears in an expression, the compiler implicitly generates a pointer to the array's first element, just as if the programmer had written &a[0].

sizeof or & operator are the exceptions to this rule.

Also, I recommend the book Expert C Programming, which uses a whole chapter to explain the difference and confusions about pointers and arrays.

I'm writing in C and compiling with GCC.

is there a better way of declaring points. I was surprised to see that points was an array. Is there some way of declaring points so it looks more like an array.

typedef struct Span
{
    unsigned long lo;
    unsigned long hi;
} Span;

typedef struct Series
{
    unsigned long *points;
    unsigned long count;
    unsigned long limit;
} Series;

void SetSpanSeries(Series *self, const Span *src)
{
    unsigned long *points;

    if (src->lo < src->hi )
    {

        // Overlays second item in series.
        points = self->points;  // a pointer in self structure
        points[0] = src->lo;
        points[1] = src->hi;
        self->count = 1;
    }
}

Now lets say that points points to a structure that is an array.

typedef struct Span
{
    unsigned long lo;
    unsigned long hi;
} Span;


span *points[4];

now how do I write these lines of code? Did I get this right?

points = self->points;  // a pointer in self structure
points[0].lo = src->lo;
points[0].hi = src->hi;

The ability to treat a pointer as an array definitely confuses most C beginners. Arrays even decay to pointers when passed as arguments to functions, giving the impression that arrays and pointers are completely interchangeable -- they aren't. An excellent description is in Expert C Programming: Deep C Secrets. (This is one of my favorite books; it's strongly recommended if you intend to understand C.)

Anyway, writing pointer[2] is the same as *(pointer+2) -- the array syntax is far easier for most people to read (and write).

Since you are using this *points variable to provide easier access to another block of memory (the pointer points in the struct Series), you cannot use an array for your local variable because you cannot re-assign the base of an array to something else. Consider the following illegal code:

int foo[10];
int *bar;
int wrong[10];

bar = foo; /* fine */
wrong = foo; /* compile error -- cannot assign to the array 'wrong' */

Another option for re-writing this code is to remove the temporary variable:

if (src->lo < src->hi) {
    self->points[0] = src->lo;
    self->points[1] = src->hi;
    self->count = 1;
}

I'm not sure the temporary variable helps with legibility -- it just saved typing a few characters at the expense of adding a lot of characters. (And a confusing variable, too.)

Decrementation / Incrementation is a basic operation but it's precendence on - -- and + ++ confused me. I'll use decrementation for illustration:

I have a set here of different styles of operating between a and b: See it working here

#include <iostream>
using namespace std;
int a=10, b=7;
int main() {
// - and -- opearator                         // Results:  Details:
    a = 10, b = 7; cout << a---b << endl;     //    3      a post-decrement        
    a = 10, b = 7; cout << a ---b << endl;    //    3      a post-decrement     
    a = 10, b = 7; cout << a- --b << endl;    //    4      b pre-decrement    
    a = 10, b = 7; cout << a-- -b << endl;    //    3      a post-decrement  
    a = 10, b = 7; cout << a--- b << endl;    //    3      a post-decrement 
    return 0;
    }

I understand that the 4 output came from the decremented b which is 7 that turned to 6 and is subtracted from a which is 10.

Also, because of the other four statements, I thought the compiler treats all of them as --- but behold, here comes the confusion of - -- results. See it working here

I think this is because of the Maximal Munch Rule. From Wiki:

In computer programming and computer science, "maximal munch" or "longest match" is the principle that when creating some construct, as much of the available input as possible should be consumed.

From Expert C Programming:

The ANSI standard specifies a convention that has come to be known as the maximal munch strategy. Maximal munch says that if there's more than one possibility for the next token, the compiler will prefer to bite off the one involving the longest sequence of characters.

This question is from Learn C the Hard Way by Zed Shaw. It's about pointers and arrays. We are given some code here:

#include <stdio.h>

int main(int argc, char *argv[])
{
  // create two arrays we care about
  int ages[] = {23, 43, 12, 89, 2};
  char *names[] = {
      "Alan", "Frank",
      "Mary", "John", "Lisa"
  };

  // safely get the size of ages
  int count = sizeof(ages) / sizeof(int);
  int i = 0;

  // first way using indexing
  for(i = 0; i < count; i++) {
      printf("%s has %d years alive.\n",
              names[i], ages[i]);
  }

  printf("---\n");

  // setup the pointers to the start of the arrays
  int *cur_age = ages;
  char **cur_name = names;

  // second way using pointers
  for(i = 0; i < count; i++) {
      printf("%s is %d years old.\n",
            *(cur_name+i), *(cur_age+i));
  }

  printf("---\n");

  // third way, pointers are just arrays
  for(i = 0; i < count; i++) {
      printf("%s is %d years old again.\n",
              cur_name[i], cur_age[i]);
  }

  printf("---\n");

  // fourth way with pointers in a stupid complex way
  for(cur_name = names, cur_age = ages;
          (cur_age - ages) < count;
          cur_name++, cur_age++)
  {
      printf("%s lived %d years so far.\n",
              *cur_name, *cur_age);
  }

  return 0;
}

The directive is to "rewrite all the array usage in this program so that it's pointers." Does this mean to do something like?

int *ptr;
ptr = &ages[0]

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

  • I don't think this is a very good book. I think it confuses some topics to make them seem harder than they really are. For a better advanced C book, I would recommend Deep C Secrets by Peter van der Linden, and for a beginner's book, I'd recommend the original K & R

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(count[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 < args_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:

free(ages); 

Note 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.

I have been trying to use local storage on ionic but my data gets lost after refreshing or after closing and re opening app. I have this module

angular.module('ionic.utils', [])

.factory('$localstorage', ['$window', function($window) {
  return {
    set: function(key, value) {
      $window.localStorage[key] = value;
    },
    get: function(key) {
      return $window.localStorage[key];
    },
    setObject: function(key, value) {
      $window.localStorage[key] = JSON.stringify(value);
    },
    getObject: function(key) {
      return JSON.parse($window.localStorage[key] || '{}');
    }
  }

}]);

and I am using the set and get method to store and extract a variable (integer), but when I close the app or refresh the page, the data doesn't get saved and I get back just an undefined value.

 $scope.currentLevel = $localstorage.get("level");

  if ($scope.currentLevel = "Undefined"){
     $scope.currentLevel = 1;
  }

always returns 1 instead of previously setted number higher than 1

I guess you have made a typo. It should be comparison operator == and not assignment =. Look at Deep C Secrets -- Million dollar bug.

I'm reading K&R and I'm almost through the chapter on pointers. I'm not entirely sure if I'm going about using them the right way. I decided to try implementing itoa(n) using pointers. Is there something glaringly wrong about the way I went about doing it? I don't particularly like that I needed to set aside a large array to work as a string buffer in order to do anything, but then again, I'm not sure if that's actually the correct way to go about it in C.

Are there any general guidelines you like to follow when deciding to use pointers in your code? Is there anything I can improve on in the code below? Is there a way I can work with strings without a static string buffer?

/*Source file: String Functions*/
#include <stdio.h>

static char stringBuffer[500];
static char *strPtr = stringBuffer;

/* Algorithm: n % 10^(n+1) / 10^(n) */
char *intToString(int n){
    int p = 1;
    int i = 0;

    while(n/p != 0)
        p*=10, i++;

    for(;p != 1; p/=10)
       *(strPtr++) = ((n % p)/(p/10)) + '0';  
    *strPtr++ = '\0';

    return strPtr - i - 1;
}

int main(){
    char *s[3] = {intToString(123), intToString(456), intToString(78910)};
    printf("%s\n",s[2]);
    int x = stringToInteger(s[2]);

    printf("%d\n", x);

    return 0;
}

Lastly, can someone clarify for me what the difference between an array and a pointer is? There's a section in K&R that has me very confused about it; "5.5 - Character Pointers and Functions." I'll quote it here:

"There is an important difference between the definitions:

char amessage[] = "now is the time"; /*an array*/
char *pmessage = "now is the time"; /*a pointer*/

amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents."

What does that even mean?

About how to use pointers and the difference between array and pointer, I recommend you read the "expert c programming" (http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298/ref=sr_1_1?ie=UTF8&qid=1371439251&sr=8-1&keywords=expert+c+programming).

I suspect this has something to do with scope, but take this code for producing a list with an initial space and subsequent commas, as taken from Expert C Programming, Deep C Secrets by Peter van der Linden:

void generate_initializer(char * string) {
    static char separator = ' ';
    printf("%c %s\n", separator, string);
    separator = ',';
}

Why does separator not get reassigned when it passes by the instruction static char separator = ' ';? I understand that 'static' is telling the compiler to allocate space for separator that extends the length of the program and to also make its scope local only to generate_initializer() but I would assume that the code wouldn't ignore an assignment operation such as this and would always reassign separator as a blank space.

static variables are allocated and initialized at compile time, not at runtime. Why? I don't know, let's break it down logically. We can imagine FOUR types of local variables:

  1. allocated and initialized at run time -- i.e., normal local variables
  2. allocated and initialized at compile time -- i.e., static variables
  3. allocated at compile time and (re-)initialized at runtime -- i.e., the sort of variables you apparently expect here
  4. allocated at runtime and initialized at compile time -- i.e., impossible

Okay, (4) is impossible and (3)...what would be the point of (3)? I can't imagine any point. Thus the way it's implemented makes sense.

PS That function, though, is pretty goofy! You can only use it on one string. Then you're done.

Just finished self-studying C with "The C Programming Language, 2nd Ed." by Brian Kernighan and Dennis Ritchie, and am looking for a good follow-up book that can kind of pick up where that book left of - specifically pertaining to programming C under Linux (sockets, threading, IPC, etc.). I did the search thing, but there are so many books (some of them quite expensive) that it is hard to pick one.

I know the Kernighan/Ritchie book is frequently used in C programming courses, so I was kind of curious what schools (and other self-learners) have been using after it?

You can read Deep C secrets as a follow-up. But I also strongly recommend you to read comp.lang.c Frequently Asked Questions. As K&R is very old , so you also need to brush up your self with C's new standards, C99/ C11.

For network programming you can follow Unix Network Programming.