Cocoa and Objective-C: Up and Running (by me) is now available from O'Reilly.

Intro to C Pointers and Dynamic Memory

Memory is the oxygen of a C program. Doing anything constructive in C involves using memory. As we saw last time, memory for stack variables is cleaned up automatically. More advanced C programing requires using dynamic memory allocation, which you have to manage yourself.

Dynamic memory allocation allows you to get blocks of memory of any size (within reason), and control them using pointers. Pointers have a reputation for being hard to deal with, but the basic mechanisms are simple. The only mental adjustment is the idea of dealing with something that refers to something else.


Warning! This is intended as a quick, rough introduction to a deep topic. The goal is to just take the edge off of C a bit, not explain every aspect of memory management. Before you go out and write sensitive code (particularly security or server software), you must take the time to understand the deeper ramifications of memory management. You've been warned.


Pointer Syntax

It's obvious a pointer points to something, but what? A pointer refers to a location in memory. In other words, it refers to a piece of data. Here's a basic pointer example:

#include <stdio.h>

main ()
{
  // declare an int variable and an int pointer variable
  int  number;
  int* pointer;

  // set a value for 'number'
  number = 5;

  // now link 'pointer' to 'number' by putting the 'addressof'
  // operator (&) in front of the number variable
  pointer = &number;

  // print values of number and pointer
  // note the %p marker is used for pointer and &number
  printf( "value of number:  %i\n", number );
  printf( "value of &number: %p\n", &number );
  printf( "value of pointer: %p\n", pointer );
  
  // print value of pointer's target (number) using
  // the asterisk (*) operator
  printf( "value of pointer's _target_: %i\n", *pointer );
}


This gives you something similar to this:

value of number:  5
value of &number: 0xbffffc5c
value of pointer: 0xbffffc5c
value of pointer's _target_: 5


Notice how the pointer simply stores the address (location) of the original variable. That's why the second and third lines of output have the same value. It may seem like this code doesn't have much practical use, but we're just trying to get the basic syntax straight first.

The key thing here is that just like a normal variable, the pointer variable has a value. With a normal variable, the literal value (such as "5") is the interesting data. With a pointer, the interesting data is what's at the memory address that it refers to (0xbffffc5c in this case). You can get the value of the target variable using the asterisk:

printf( "value of pointer's target: %i\n", *pointer );

This is called dereferencing. The star does all the necessary low-level calculations to fetch the data so you don't have to do the math yourself.

Hexidecimal Notation

The value of pointer is displayed in hexadecimal format (just like web colors). Don't be intimdated by the alien notation, it's still just a number. Hexidecimal numbers are expressed in base 16, meaning each digit has 16 different values. Decimal numbers (the ones we're used to) are expressed in base 10:

Decimal has 10 possible values for each digit:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
  
Hexidecimal has 16 possible values for each digit:                  
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f

                                                    
The 0x part is just a prefix to tell C that it's a hexidecimal number. The actual numeric value is bffffc5c. So now you can sleep tonight knowing what is meant by the term "base 16".

Pointers Making You See Stars?

Pointer syntax tends to confuse novice C programmers. The problem is that the asterisk (aka "star") is used for two distinct purposes: in a pointer declaration and when returning the value of the target.

Here's an example of each:

// declare a basic int variable  
int number = 18;

// use the asterisk to _declare_ a pointer
int * numberPointer;

// assign a value to the pointer
numberPointer  = &number;

// use the asterisk again, this time to _fetch_
// the value of the _target_ variable (number)

printf ("Value of target: %i", *numberPointer);


In an ideal world, a pointer declaration wouldn't contain an asterisk, but this is the syntax that we have in our universe.

Copy Versus Reference

Keep in mind the difference between a pointer which refers to a variable and a copy of a variable. Here's an example:

#include <stdio.h>

main ()
{
  float   myNumber;
  float   myNumberCopy;
  float * myNumberPointer;
  
  // first, set an initial value  
  myNumber = 1.618;
  
  // copy the value
  myNumberCopy = myNumber;
  
  // make a pointer to the value using the
  // ampersand, known as the "addressof" operator
  myNumberPointer = &myNumber;
  
  // change the original
  myNumber = 2.0;
  
  // now check the values.
  // be sure to use the star (*) to fetch the value
  // of myNumberPointer's target
  
  printf( "myNumber: %f\n", myNumber );
  printf( "myNumberCopy: %f\n", myNumberCopy );
  printf( "myNumberPointer: %f\n", *myNumberPointer );
}


Here's the output:

myNumber: 2.000000
myNumberCopy: 1.618000
myNumberPointer: 2.000000


The copy gets its own value, but the pointer stays linked to the original.

Malloc and Free Functions

The memory for basic variables such as ints, floats and simple arrays are handled automatically. Sometimes, though, you need to exercise more control. Dynamic memory management means that you can reserve a large block of memory, but you have to take reponsibility for freeing it later.

The malloc family of functions are used to deal with these blocks of memory. The most basic of these is malloc(), which takes a size as input and returns a pointer to the a new block of memory. The term "malloc" is short for "memory allocate". Here's a simple example:

// reserve 4 bytes of memory
void * memoryBlock = malloc ( 4 );


The "void *" type means that the memoryBlock will store a pointer to a block of memory with an undefined type. That is, we're not specifying what kind of data will go in there. When you're done with the block of memory, you have to release it using the free() function:

free ( memoryBlock );

If you don't do this, you'll have a memory leak on your hands (yuck!).

Making a Memory Block Useful

Allocating 4 byte memory block isn't all that interesting. What we really want to do is get a memory block that can hold a certain number of values. For example, if we want to hold 20 int values, we can do this:

void * memoryBlock = malloc ( sizeof(int) * 20 );

We use the sizeof() function to calculate the size of a particular type of variable. That number is then multiplied by the number of values we want to store (20).

We can also use a variation of the malloc function, called calloc. The calloc function takes two arguments, a value count and the base value size. It also clears the memory before returning a pointer, which is useful in avoiding unpredictable behavior and crashes in certain cases:

void * memoryBlock = calloc ( 20, sizeof(int) );

A memory block like this can effectively be used as a more flexible array. This approach is actually much more common in real-world C programs. It's also more predictable and flexible than a "variable size array" (mentioned in the previous tutorial).

But how do we get and set values in each slot? One common approach is to use the ++ and -- operators to move the pointer forward or back in the memory block. In order to do this, we should set the correct type for the returned memory block:

// create a "moveable" int pointer
int * memoryBlock = calloc ( 10, sizeof(int) );


This allow the ++ operator to move forward the exact size of an int variable each time, effectively moving forward one "slot" in our array-like memory block.

#include <stdio.h>
#include <stdlib.h> // for calloc and free
#include <time.h>   // for random seeding

main ()
{
  const int count = 10;
  int * memoryBlock = calloc ( count, sizeof(int) );
  
  if ( memoryBlock == NULL )
  {
    // we can't assume the memoryBlock pointer is valid.
    // if it's NULL, something's wrong and we just exit
    return 1;
  }

  // currentSlot will hold the current "slot" in the,
  // array allowing us to move forward without losing
  // track of the beginning. Yes, C arrays are primitive
  //
  // Note we don't have to do '&memoryBlock' because
  // we don't want a pointer to a pointer. All we
  // want is a _copy_ of the same memory address
    
  int * currentSlot = memoryBlock;


  // seed random number so we can generate values
  srand(time(NULL));
  
  int i;    
  for ( i = 0; i < count; i++ )
  {
    // use the star to set the value at the slot,
    // then advance the pointer to the next slot    
    *currentSlot = rand();
    currentSlot++;
  }

  // reset the pointer back to the beginning of the
  // memory block (slot 0)
  currentSlot = memoryBlock;

  for ( i = 0; i < count; i++ )
  {
    // use the star to get the value at this slot,
    // then advance the pointer
    printf("Value at slot %i: %i\n", i, *currentSlot);
    currentSlot++;
  }

  // we're all done with this memory block so we
  // can free it  
  free( memoryBlock );
}


This isn't the only correct way to do this sort of thing, just one approach. Also, keep in mind that since a memory block can be treated as an array, you're likely to see things like this in code:

char * myString;

Since a string is an array of individual characters, a memory block filled with individual characters can act as a string as well.

Arrays of Arrays

Multi-dimensional arrays are not unique to C, but deserve mention here. They basically come in two flavors. The major basic form:

int grid [10][10];

...and the more flexible form you're likely to see in the wild:

int ** numberGrid;

This may look a bit strange, but remember two points:

1. A memory block is represented as a pointer (void * memoryBlock)
2. A memory block can act as an array

So if this is an array:

int * numberArray;

... this can be an array of arrays:

int ** numberGrid;

Be careful, though, because this sort of declaration could also be treated as an array of pointers to specific ints, which is a subtle difference.

Array of Strings

Dealing with strings in C is really deserving of its own post so I'm not going to go into deep details here, but there's one convention that you should be aware of for general code reading:

char ** inputValues;

This sort of thing is usually an array of strings. Remember, a string is an array of individual characters, so a an array of strings is a two-dimension array of characters.

Final Example

Here's a short program that illustrates all of these points.

#include <stdio.h>
#include <stdlib.h>

int main ()
{
  // number of strings
  const int count = 5;
  
  // declare an array of strings
  char ** stringArray = calloc ( count, sizeof(char *) );
  printf("stringArray address: %p\n", stringArray);

  // if the memory we asked for isn't available, return
  if ( stringArray == NULL )
  {
    return 1;
  }
  
  // this is what we'll use to move through the
  // memory block
  char ** currentString = stringArray;
  int i;  

  printf("Initial currentString address: %p\n", currentString);
    
  // now we have to loop through the memory block and
  // allocate memory for a string at each "array" slot.
  //
  // note that the asprintf() function doesn't return
  // the string. Instead, it writes directly to the
  // slot in the memory block
  for ( i = 0; i < count; i++ )
  {
    asprintf ( currentString, "String %i", i );
    currentString++;
    printf("currentString address: %p\n", currentString);  
  }
  
  // reset memory block to the original address.  
  // In other words, go the beginning of the "array"
  currentString = stringArray;
  printf("currentString address after reset: %p\n", currentString);
  

  // display the string at this particular slot.
  // we have to use the star to de-reference
  for ( i = 0; i < count; i++ )
  {
    printf( "%s\n", *currentString );
    currentString++;
  }

  // reset
  currentString = stringArray;

  // loop through and free the memory for the
  // string at each slot
  for ( i = 0; i < count; i++ )
  {
    free ( *currentString );
    currentString++;
  }

  // now free the memory block itself
  free ( stringArray );
}


This should give some output like this:

stringArray address: 0x500120
Initial currentString address: 0x500120
currentString address: 0x500124
currentString address: 0x500128
currentString address: 0x50012c
currentString address: 0x500130
currentString address: 0x500134
currentString address after reset: 0x500120
String 0
String 1
String 2
String 3
String 4


Notice how each time we do currentString++, the address increases by four bytes:

500120 > 500120 > 500124...

This allows us to move through the memory block and treat it as an array. After the loop is complete, we have to "reset" currentString by reassigning its value to that of stringArray:

currentString = stringArray;

If we don't do this and attempt to keep moving through the array, we'll run off the end of the memory block and bad things will happen. This is how bugs are born! There are various tools to avoid these sorts of situations, but those are beyond the scope of this post.

Wrap Up

You should now have at least a basic grasp on how pointers and dynamic memory management work in C. Now go out and experiment on your own. Go on, get.
Design Element
Intro to C Pointers and Dynamic Memory
Posted Feb 24, 2006 — 38 comments below




 

Jesper — Feb 25, 06 840

Just posting this mid-reading, lest I forget later:

"For example, if we want to hold 20 ***float*** values, we can do this:

void * memoryBlock = malloc ( sizeof(***int***) * 20 );"

Scott Stevenson — Feb 25, 06 842 Scotty the Leopard

Fixed, thanks.

Ben — Feb 25, 06 846

This is great, an awesome refresher and excellent examples of Obj-C which I am not 100% used to. This will become some reference material for me.

One question, how often do you find yourself coming back to these first princples when developing for Apple? Especially when there so much more framework and use of Collections is possible? I'm very interested to know, or is this information more about having a solid foundation?

Scott Stevenson — Feb 25, 06 848 Scotty the Leopard

This is great, an awesome refresher and excellent examples of Obj-C which I am not 100% used to.

I'm glad you find it useful, but it's probably unfair to call this Obj-C. Really more just plain C. :)

One question, how often do you find yourself coming back to these first princples when developing for Apple?

The Foundation classes can replace raw C memory management in many or most cases, but higher-end Cocoa apps often need the speed that you get from working at a lower level. You also may need to know this stuff if you want to use a C library in your app.

Scott Stevenson — Feb 27, 06 851 Scotty the Leopard

I should probably clarify my last statement a bit:

but higher-end Cocoa apps often need the speed that you get from working at a lower level

What I mean by this is that higher-end apps often need optimization in certain, specific areas of the code, typically found using a profiling tool like Shark. In those places you might be better off using raw C data structures. In most cases, though, you can use Foundation or Core Foundation.

I don't want to leave anyone with the wrong impression. The Foundation storage classes are made up of highly-optimized, industrial-strength code. They fit the bill in the vast majority of cases.

Erik — Feb 27, 06 852

Nice explanation of these concepts. This is one topic that's often missing from C introductory tutorials.

Peter — Apr 10, 06 1096

This article starts out good, but goes quite astray starting at "arrays of arrays". This way of thinking of "int **p" will lead a programmer into a world of hurt.

"int **p" does not declare an array of arrays, nor a two-dimensional array of integers. It declares a pointer to a pointer (to an int). The biggest difference occurs when you pass "p" as a parameter to something, or try to make an "extern" declaration that references it.

Scott: I'd be glad to discuss this at length with you if you want to email me. A good foundation in pointers can set a programmer up for life; a shaky foundation can ruin him for years.

Scott Stevenson — Apr 10, 06 1097 Scotty the Leopard

This article starts out good, but goes quite astray starting at "arrays of arrays"

I guess I don't quite agree. Many tutorials will explain pointers in terms of the internal mechanics, but my feeling is that teaching through actual, day-to-day use works better in many cases.

I also don't think the tutorial creates quite as dire a situation as you suggest. This is just meant as a starting point for practical basics. Trying to explain all the details would miss the point.

Also note that I say that notation can be an array of arrays, which I think is true enough for what I set out to do here.

James — Apr 28, 06 1145

A very nice free introduction to pointers and memory in C (as well as a very nice introduction to C, both somewhat longer and more detailed than yours) can be found at the Stanford CS Education Library.

I don't know Objective-C at the moment, so I don't know how important it is to get into grittier details earlier, but there you go.

JetLoong — May 09, 06 1196

Thank u for this introduction. U helped me out a lot. I was really confused at the beginning with the declaration of pointers with the asterisk and how to catch the actual value behind the pointer.
Now I can do further readings on C books ^^ Thx to u

DRAY — May 11, 06 1216

Very helpful article for C newbies!

One question though... ( ...always a catch eh?)

Why is it that I get the following when freeing the "inner array mem" with

// reset
currentString = stringArray;
for...
{
free( *currentString );
currentString++;
}

*** malloc[9384]: Deallocation of a pointer not malloced: 0x2f80; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
*** malloc[9384]: Deallocation of a pointer not malloced: 0x2f88; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
*** malloc[9384]: Deallocation of a pointer not malloced: 0x2f8c; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
*** malloc[9384]: Deallocation of a pointer not malloced: 0x2f90; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
*** malloc[9384]: Deallocation of a pointer not malloced: 0x2f94; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug

thanks again for the great work!

David

DAniel — Jun 28, 06 1426

I think it's a very good article... liked it very much..
I'm trying to deal with a little subject , may be you could help me.
Supose I declare a pointer to char and allocate some memory for it, and then, in the middle of the program turns out to be insuficient. how could I enlarge the amount of space allocated for it. for example, when reading unknown length input from the keybord.
Other thing I'm having some problem with is when trying to get the size of an array of pointers to char (char *ptrarr[]) . How could I know how many pointers to char are there ? sizeof(ptrarr) doesn't work.

Henrik N — Oct 20, 06 2113

Typo in the first paragraph: "programing" should be "programming".

Galen — Jan 02, 07 2978

Hi Scott. A bit late with this, sorry.

This is a really great article. I like your approach. One problem I sill have with pointers is this: Why and when should you use pointers? The copy example was a good one but I have the feeling that that just scratches the surface. Especially when looking at C, C++ or Objective-C code. Pointers seem to be everywhere with absolutely no rhyme or reason. A post on why and when to use pointers would be excellent.

Thanks!!

Scott Stevenson — Jan 02, 07 2980 Scotty the Leopard

Why and when should you use pointers?

There are many things you simply cannot do without them. In a sense, pointers are a way for different parts of a program to access the same data. In some cases, they're the only way. In fact, the only thing you can really do without pointers is pass around individual number values or single characters. As soon as you want to use arrays, strings (blocks of text), or Cocoa objects you need pointers.

I think a lot of the confusion from pointers stems from the name. It make it sounds like a pointer is active, that it does something. It really does not. It's just a number that uniquely indentifies a piece of data in memory. It might be easier to actually think of them as unique IDs.

In Cocoa, all object variables are pointers because all of them are stored in the same central location -- in "heap" memory. That is, if you create an object inside a function, it doesn't automatically "go away" at the end of the function. The only way to "reach" the object in heap memory is to refer to it by its unique ID -- the pointer value.

I hope that helps.

Herb Payerl — Jan 22, 07 3380

This is a great tutorial.

I think one thing that might deserve further explanation is that the function asprintf actually allocates memory for the strings it creates. The calloc function just reserves space for an array of pointers.

Thanks

Michael Dreher — May 06, 07 4044

Hi,

I just read this interesting tutorial, coming from cocoadev's intro to C. I already knew basically all the concepts, but I have never seen a better introduction to pointers than yours. Thumbs up!

One mistake I recognized in your tutorial is the following:

Notice how each time we do currentString++, the address increases by four bytes:

500120 > 500120 > 500124...

which does not really increase by four bytes each time.

I really like your way of presenting, like pointers here, or the great introduction to classes and objects in the cocoadev tutorials. And I hope you are using this talent as a professional instructor or teacher. If not, you should strongly consider it.

Michael

Chris Benedict — Sep 26, 07 4654

Thanks for the great tutorial. I've been wanting to learn this stuff for a while and I found this tutorial a great way to get an idea of what the picture looks like before looking at the separate pixels (does that make sense? :P )

I really hope to see more tutorials like this that get progressively more in depth, I have really enjoyed going from your "Learn C" tutorial on Cocoa Dev Center to "C Memory and Arrays" now to "C Pointers and Dynamic Memory".

My only question is where can I go now to learn the nitty gritty details and mechanics?

Sean McGinty — Oct 27, 07 4868

Scott,

Thanks for this post and the others on C. I've recently started exploring Cocoa and it's been quite a while since I've looked at C code. I looked around the web for a refresher but couldn't find one that met my needs until now. Thanks again!

Alison — Mar 29, 08 5689

I've been trying to get started in objective-C, and discovered that without a solid understanding of C, many aspects of it are completely alien. This tutorial along with your others has helped to fill in the gaps for me (coming from a scripting background where memory management and pointers are completely unheard of).

Many thanks.

Scott Stevenson — Mar 30, 08 5692 Scotty the Leopard

@Alison: This tutorial along with your others has helped to fill in the gaps for me

Hi, Alison. I'm glad it helped.

Rebecca — Apr 01, 08 5699

The last time I touched C was 10+ years ago. This is a great refresher.

I was a little puzzled by what you meant in the final example:
//we have to use the star to de-reference

So I added another printf for my own reference:
printf("currentString is %p\n", currentString);

to compare the difference between currentString and *currentString at this point.

Then I realized currentString is just the address (or the ID, using your words), and *currentString is the actual value contained in the reserved space.

Just thought I should point out the obvious for other dummies like myself.

Dharm — Jun 10, 08 6061

I would have liked to see some reference to Objective C type variables in this regard. For example, I am having an array (NSArray *p) of NSXMLNode which I got from nodesForXPath of an html page. Now, I wanted to shift the array by one element i.e. typically in C we do (*p)++ as described in this tutorial, but this gives errors in Xcode and it fails to compile.

So, apart from using subarrayWithRange 1-[array count], is there a more efficient way to do this like in C style?
Thanks.

Dharm — Jun 10, 08 6062

Just a correction, instead of (*p)++ , it should read p++.

Scott Stevenson — Jun 11, 08 6065 Scotty the Leopard

@Dharm: Now, I wanted to shift the array by one element i.e. typically in C we do (*p)++ as described in this tutorial, but this gives errors in Xcode and it fails to compile.

You can't manually increment the pointer, which is by design. Cocoa supports both NSArray objects and the regular C-style arrays (but Cocoa methods rarely create C-style arrays). NSArrays are much safer to use, partially because they don't let you do things like that.

If you want to create a C-style buffer from an NSArray, you can use NSArray's -getObjects: method. That said, I'd strongly encourage you to reconsider your design before doing that because it's generally bad practice for Cocoa and is not required in most cases. NSArray is incredibly fast, so you really shouldn't need to work about performance in most cases.

Jamie Lemon — Mar 26, 09 6673

Great tutorial - thanks very much

Eapen — Jul 11, 09 6828

I was going through some of your tutorials on Objective C and this post and you explain languages/concepts really well and concisely.

It is really appreciated.

Eapen — Jul 11, 09 6829

I forgot to add that I was referring to your tutorials on http://cocoadevcentral.com/d/learn_objectivec/

Steffen Frost — Sep 28, 09 6905

Hi Steven

In your first example you declare a pointer with...

// declare an int variable and an int pointer variable
int number;
int* pointer; <-- no space between 'int' and '*'

In the second example...

// use the asterisk to _declare_ a pointer
int * numberPointer; <-- space between 'int' and '*'

I compiled and ran both with and without the space between 'int' and '*', and it doesn't make a difference. Little things like this can through you off if you are trying to learn syntax.

Just a nit.

Steffen Frost — Sep 28, 09 6906

I would make a small change to this

... printf( "myNumber: %f\n", myNumber ); printf( "myNumberCopy: %f\n", myNumberCopy ); printf( "myNumberPointer: %f\n", *myNumberPointer ); } Here's the output: myNumber: 2.000000 myNumberCopy: 1.618000 myNumberPointer: 2.000000

Change to
... printf( "myNumber: %f\n", myNumber ); printf( "myNumberCopy: %f\n", myNumberCopy ); printf( "*myNumberPointer: %f\n", *myNumberPointer ); } Here's the output: myNumber: 2.000000 myNumberCopy: 1.618000 *myNumberPointer: 2.000000

Steffen Frost — Sep 28, 09 6907

Another point that might be confusing. When you first introduced the concept of a pointer, you used the following example:

// declare an int variable and an int pointer variable int number; int* pointer;

My thinking was that a pointer had to be an integer since it was an address in memory, so that made sense. Then in a subsequent example you declared...

main () { float myNumber; float myNumberCopy; float * myNumberPointer; ...

This confused me, since how could an address, i.e. pointer, be a float? Later did I realize that the way to interpret "float* " or "int*" is, respectively, "a float's pointer" or "an integer's pointer". Another way to think of it is "a pointer for a integer variable" or "a pointer for a float variable".

Steffen Frost — Sep 28, 09 6908

Just to be cute:

#include main () { int number; // declare an int var int* pointer; // declare an integer's pointer var number = 5; //set value for 'number' var pointer = &number; // pointer is 'addressof' (& operator) of num printf (" number is: %i\n", number); printf ("&number is: %p\n", &number); // the 'addressof' the num printf ("pointer is: %p\n", pointer); // and here printf ("*pointer is: %i\n", *pointer); printf ("*&number is: %i\n", *&number); // contents of addressof the variabe }

Steffen Frost — Sep 28, 09 6909

Just to be cute and compilable...
#include main () { int number; // declare an int var number = 5; //set value for 'number' var printf (" number is: %i\n", number); printf (" &number is: %p\n", &number); // the 'addressof' the num printf ("*&number is: %i\n", *&number); // contents of addressof the variabe }

Bill — Oct 30, 09 6976

Typo above:

This allow the ++ operator to move forward the exact size of an int variable each time

Should be: this allows

Bill — Oct 30, 09 6977

More typos:

Remember, a string is an array of individual characters, so a an array of strings is a two-dimension array of characters

Should be: so an array...

// In other words, go the beginning of the "array"

Should be: go to the beginning...

Bill Tubbs — Oct 30, 09 6978

I agree with Herb Payerl's comment above (Jan 22, 07 3). The thing missing from the explanation of the final example is an explanation of the asprintf function.
When reading the code I just couldn't see how the calloc function could possibly be reserving enough memory. As far as I could see it reserves space for 5 pointers, not space for 5 entire strings. Not knowing that aspintf also allocates memory I couldn't see where the string data was being stored. Since the danger with pointers is overwriting memory that hasnt been allocated this was causing me some consternation!

I found this on the web. Hope it helps:
"The asprintf function is nearly identical to the simpler sprintf, but is much safer, because it dynamically allocates the string to which it sends output, so that the string will never overflow."

Thanks, all the tutorials are excellent.

Write paper — Jan 06, 10 7082

Thanks for great stuff!
Buy term paper

Nitpicker — Feb 06, 10 7368

You use hexidecimal mostly instead of the correct hexadecimal (which does appear once).




 

Comments Temporarily Disabled

I had to temporarily disable comments due to spam. I'll re-enable them soon.




Technorati Profile
Copyright © Scott Stevenson 2004-2008