A Tutorial on Pointers and Arrays in C
by Ted Jensen
Version 1.2 (HTML version)
Feb. 2000
This material is hereby placed in the public domain.
Available in various formats via http://www.netcom.com/~tjensen/ptr/cpoint.htm
Preface
This document is intended to introduce pointers to beginning programmers in the C programming language. Over several years of reading and contributing to various conferences on C including those on the FidoNet and UseNet, I have noted a large number of newcomers to C appear to have a difficult time in grasping the fundamentals of pointers. I therefore undertook the task of trying to explain them in plain language with lots of examples.
The first version of this document was placed in the public domain, as is this one. It was picked up by Bob Stout who included it as a file called PTR-HELP.TXT in his widely distributed collection of SNIPPETS. Since that original 1995 release, I have added a significant amount of material and made some minor corrections in the original work.
In the HTML version 1.1 I made a number of minor changes to the wording as a result of comments emailed to me from around the world. In version 1.2 I updated the first two chapters to acknowledge the shift from 16 bit compilers to 32 bit compilers on PCs.
Acknowledgements
There are so many people who have unknowingly contributed to this work because of the questions they have posed in the FidoNet C Echo, or the UseNet Newsgroup comp.lang.c, or several other conferences in other networks, that it would be impossible to list them all. Special thanks go to Bob Stout who was kind enough to include the first version of this material in his SNIPPETS file.
About the Author
Ted Jensen is a retired Electronics Engineer who worked as a hardware designer or manager of hardware designers in the field of magnetic recording. Programming has been a hobby of his off and on since 1968 when he learned how to keypunch cards for submission to be run on a mainframe. The mainframe had 64K of magnetic core memory.
Use of this Material
Everything contained herein is hereby released to the Public Domain. Any person may copy or distribute this material in any manner they wish. The only thing I ask is that if this material is used as a teaching aid in a class, I would appreciate it if it were distributed in its entirety, including all chapters, the preface, and the introduction. I would also appreciate it if, under such circumstances, the instructor of such a class would drop me a note at one of the addresses below informing me of this. I have written this with the hope that it will be useful to others and since I am not asking any financial remuneration, the only way I know that I have at least partially reached that goal is via feedback from those who find this material useful.
By the way, you need not be an instructor or teacher to contact me. I would appreciate a note from anyone who finds the material useful, or who has constructive criticism to offer. I am also willing to answer questions submitted by email at the addresses shown below.
Other Versions of this Document
In addition to this hypertext version of this document, I have made available other versions more suitable for printing or for downloading of the entire document. If you are interested in keeping up to date on my progress in that area, or want to check for more recent versions of this document, see my web site at http://www.netcom.com/~tjensen/ptr/cpoint.htm.
Ted Jensen
Redwood City, California
tjensen@ix.netcom.com
Feb. 2000
Introduction
If you want to be proficient in the writing of code in the C programming language, you must have a thorough working knowledge of how to use pointers. Unfortunately, C pointers appear to represent a stumbling block to newcomers, particularly those coming from other computer languages such as Fortran, Pascal, or Basic.
To aid those newcomers in the understanding of pointers I have written the following material. To get the maximum benefit from this material, I feel it is important that the user be able to run the code in the various listings contained in the article. I have attempted, therefore, to keep all code ANSI compliant so that it will work with any ANSI compliant compiler. I have also tried to carefully block the code within the text. That way, with the help of an ASCII text editor, you can copy a given block of code to a new file and compile it on your system. I recommend that readers do this as it will help in understanding the material.
Chapter 1: What is a Pointer?
One of those things beginners in C find difficult is the concept of pointers. The purpose of this tutorial is to provide an introduction to pointers and their use to these beginners.
I have found that often the main reason beginners have a problem with pointers is that they have a weak or minimal feeling for variables, as they are used in C. Thus we start with a discussion of C variables in general.
A variable in a program is something with a name, the value of which can vary. The way the compiler and linker handles this is that it assigns a specific block of memory within the computer to hold the value of that variable. The size of that block depends on the range over which the variable is allowed to vary. For example, on 32 bit PCs the size of an integer variable is 4 bytes. On older 16 bit PCs integers were 2 bytes. In C the size of a variable type such as an integer need not be the same on all types of machines. Furthermore there is more than one type of integer variable in C. We have integers, long integers, and short integers which you can read up on in any basic text on C. This document assumes the use of a 32 bit system with 4 byte integers.
If you want to know the size of the various types of integers on your system, running the following code will give you that information.
#include <stdio.h>
int main()
{
printf("size of a short is %d\n", sizeof(short));
printf("size of a int is %d\n", sizeof(int));
printf("size of a long is %d\n", sizeof(long));
} When we declare a variable we inform the compiler of two things, the name of the variable and the type of the variable. For example, we declare a variable of type integer with the name k by writing:
int k; On seeing the int part of this statement the compiler sets aside 4 bytes of memory on a PC to hold the value of the integer. It also sets up a symbol table. In that table it adds the symbol k and the relative address in memory where those 4 bytes were set aside.
Thus, later if we write:
k = 2; we expect that, at run time when this statement is executed, the value 2 will be placed in that memory location reserved for the storage of the value of k. In C we refer to a variable such as the integer k as an “object.”
In a sense there are two values associated with the object k. One is the value of the integer stored there, 2 in the above example, and the other the value of the memory location, that is, the address of k. Some texts refer to these two values with the nomenclature rvalue and lvalue respectively.
In some languages, the lvalue is the value permitted on the left side of the assignment operator =, the address where the result of evaluation of the right side ends up. The rvalue is that which is on the right side of the assignment statement, the 2 above. Rvalues cannot be used on the left side of the assignment statement. Thus 2 = k; is illegal.
An object is a named region of storage; an lvalue is an expression referring to an object.
However, at this point, the definition originally cited above is sufficient. As we become more familiar with pointers we will go into more detail on this.
Okay, now consider:
int j, k;
k = 2;
j = 7; <-- line 1
k = j; <-- line 2 In the above, the compiler interprets the j in line 1 as the address of the variable j, its lvalue, and creates code to copy the value 7 to that address. In line 2, however, the j is interpreted as its rvalue since it is on the right hand side of the assignment operator. That is, here the j refers to the value stored at the memory location set aside for j, in this case 7. So, the 7 is copied to the address designated by the lvalue of k.
Now, let’s say that we have a reason for wanting a variable designed to hold an lvalue, an address. Such a variable is called a pointer variable. In C when we define a pointer variable we do so by preceding its name with an asterisk. For example:
int *ptr; ptr is the name of our variable. The asterisk informs the compiler that we want a pointer variable, and the int says that we intend to use our pointer variable to store the address of an integer.
Suppose now that we want to store in ptr the address of our integer variable k. To do this we use the unary & operator and write:
ptr = &k The dereferencing operator is the asterisk and it is used as follows:
*ptr = 7; That will copy 7 to the address pointed to by ptr. Thus if ptr contains the address of k, the above statement will set the value of k to 7.
Similarly, we could write:
printf("%d\n", *ptr); One way to see how all this stuff fits together would be to run the following program and then review the code and the output carefully.
------------ Program 1.1 ---------------------------------
/* Program 1.1 from PTRTUT10.TXT 6/10/97 */
#include <stdio.h>
int j, k;
int *ptr;
int main(void)
{
j = 1;
k = 2;
ptr = &k
printf("\n");
printf("j has the value %d and is stored at %p\n", j, (void *)&j);
printf("k has the value %d and is stored at %p\n", k, (void *)&k);
printf("ptr has the value %p and is stored at %p\n", ptr, (void *)&ptr);
printf("The value of the integer pointed to by ptr is %d\n", *ptr);
return 0;
} Note: We have yet to discuss those aspects of C which require the use of the (void *) expression used here. For now, include it in your test code. We will explain the reason behind this expression later.
- A variable is declared by giving it a type and a name, for example
int k;. - A pointer variable is declared by giving it a type and a name, for example
int *ptr;. - Once a variable is declared, we can get its address by preceding its name with the unary
&operator, as in&k. - We can dereference a pointer, that is, refer to the value of that which it points to, by using the unary
*operator as in*ptr. - An lvalue of a variable is the value of its address. The rvalue of a variable is the value stored in that variable.
References for Chapter 1
- "The C Programming Language" 2nd Edition
B. Kernighan and D. Ritchie
Prentice Hall
ISBN 0-13-110362-8
Chapter 2: Pointer Types and Arrays
Okay, let’s move on. Let us consider why we need to identify the type of variable that a pointer points to, as in:
int *ptr; One reason for doing this is so that later, once ptr points to something, if we write:
*ptr = 2; the compiler will know how many bytes to copy into that memory location pointed to by ptr. If ptr was declared as pointing to an integer, 4 bytes would be copied.
Now, let’s say we point our integer pointer ptr at the first of ten integers in a row. What happens when we write:
ptr + 1; Because the compiler knows this is a pointer and that it points to an integer, it adds 4 to ptr instead of 1, so the pointer points to the next integer.
Consider the following:
int my_array[] = {1,23,17,4,-5,100}; We can access those integers either with array notation or via a pointer:
int *ptr;
ptr = &my_array[0]; The following code illustrates this:
----------- Program 2.1 -----------------------------------
/* Program 2.1 from PTRTUT10.HTM 6/13/97 */
#include <stdio.h>
int my_array[] = {1,23,17,4,-5,100};
int *ptr;
int main(void)
{
int i;
ptr = &my_array[0]; /* point our pointer to the first
element of the array */
printf("\n\n");
for (i = 0; i < 6; i++)
{
printf("my_array[%d] = %d ",i,my_array[i]); /*<-- A */
printf("ptr + %d = %d\n",i, *(ptr + i)); /*<-- B */
}
return 0;
} In C, the standard states that wherever we might use &var_name[0] we can replace that with var_name, thus:
ptr = my_array; This leads many texts to state that the name of an array is a pointer. I prefer to mentally think “the name of the array is the address of first element in the array.” While we can write ptr = my_array;, we cannot write my_array = ptr; because my_array is a constant.
To minimize type compatibility problems among pointers, C provides for a pointer of type void. We can declare such a pointer by writing:
void *vptr; A void pointer is a generic pointer. For example, while C will not permit the comparison of a pointer to type integer with a pointer to type character, either of these can be compared to a void pointer.
Chapter 3: Pointers and Strings
The study of strings is useful to further tie in the relationship between pointers and arrays. It also makes it easy to illustrate how some of the standard C string functions can be implemented. Finally it illustrates how and when pointers can and should be passed to functions.
In C, strings are arrays of characters terminated with a binary zero character written as '\0'.
char my_string[40];
my_string[0] = 'T';
my_string[1] = 'e';
my_string[2] = 'd';
my_string[3] = '\0'; Of course, C also permits:
char my_string[40] = {'T', 'e', 'd', '\0'};
char my_string[40] = "Ted"; Now, consider the following program:
------------------program 3.1-------------------------------------
/* Program 3.1 from PTRTUT10.HTM 6/13/97 */
#include <stdio.h>
char strA[80] = "A string to be used for demonstration purposes";
char strB[80];
int main(void)
{
char *pA; /* a pointer to type character */
char *pB; /* another pointer to type character */
puts(strA); /* show string A */
pA = strA; /* point pA at string A */
puts(pA); /* show what pA is pointing to */
pB = strB; /* point pB at string B */
putchar('\n'); /* move down one line on the screen */
while(*pA != '\0') /* line A (see text) */
{
*pB++ = *pA++; /* line B (see text) */
}
*pB = '\0'; /* line C (see text) */
puts(strB); /* show strB on screen */
return 0;
}
--------- end program 3.1 ------------------------------------- The above illustrates a simple way of copying a string. We can proceed to creating our own replacement for the standard strcpy():
char *my_strcpy(char *destination, char *source)
{
char *p = destination;
while (*source != '\0')
{
*p++ = *source++;
}
*p = '\0';
return destination;
} In the standard form, the prototype would normally be:
char *my_strcpy(char *destination, const char *source); One important lesson here is that *ptr++ means return the value pointed to by ptr and then increment the pointer. By contrast, (*ptr)++ would increment the thing pointed to.
When we write functions to manipulate arrays, we normally pass the address of the array and any auxiliary information such as the number of items to be copied. For example:
void int_copy(int *ptrA, int *ptrB, int nbr); Chapter 4: More on Strings
Let’s back up a little and look at what was done in Chapter 3 on copying of strings but in a different light.
char *my_strcpy(char dest[], char source[])
{
int i = 0;
while (source[i] != '\0')
{
dest[i] = source[i];
i++;
}
dest[i] = '\0';
return dest;
} Since parameters are passed by value, what actually gets passed is the address of the first element of each array. This would tend to imply that source[i] is the same as *(source + i). In fact, this is true. Pointer arithmetic is the same thing as array indexing.
Thus:
a[3] = 'x'; is the same as:
3[a] = 'x'; That is a curiosity more than anything else.
Another small optimization is that:
while (*source != '\0') can be written as:
while (*source) since the expression becomes false at the same point in either case.
Chapter 5: Pointers and Structures
We can declare the form of a block of data containing different data types by means of a structure declaration.
struct tag {
char lname[20]; /* last name */
char fname[20]; /* first name */
int age; /* age */
float rate; /* e.g. 12.75 per hour */
}; Suppose we want to pass a pointer to such a structure to a function. We declare the pointer with:
struct tag *st_ptr; and point it to our example structure with:
st_ptr = &my_struct; We can dereference the pointer as:
(*st_ptr).age = 63; or, more commonly, as:
st_ptr->age = 63; Example:
------------ program 5.2 ---------------------
/* Program 5.2 from PTRTUT10.HTM 6/13/97 */
#include <stdio.h>
#include <string.h>
struct tag{
char lname[20];
char fname[20];
int age;
float rate;
};
struct tag my_struct;
void show_name(struct tag *p);
int main(void)
{
struct tag *st_ptr;
st_ptr = &my_struct;
strcpy(my_struct.lname,"Jensen");
strcpy(my_struct.fname,"Ted");
printf("\n%s ",my_struct.fname);
printf("%s\n",my_struct.lname);
my_struct.age = 63;
show_name(st_ptr);
return 0;
}
void show_name(struct tag *p)
{
printf("\n%s ", p->fname);
printf("%s ", p->lname);
printf("%d\n", p->age);
} Chapter 6: Some More on Strings, and Arrays of Strings
We pointed out earlier that we could write:
char my_string[40] = "Ted"; or simply:
char my_name[] = "Ted"; In some code, instead of the above, you might see:
char *my_name = "Ted"; Those are not identical in storage behavior. In the array notation, the characters occupy the array storage itself. In the pointer notation, you also need storage for the pointer variable.
Consider:
void my_function_A(char *ptr)
{
char a[] = "ABCDE"
.
.
}
void my_function_B(char *ptr)
{
char *cp = "FGHIJ"
.
.
} As long as we are discussing the relationship between pointers and arrays, let’s move on to multi-dimensional arrays.
char multi[5][10]; Conceptually, this is an array of 5 arrays of 10 characters each. If filled with values, memory might look like:
multi[0] = {'0','1','2','3','4','5','6','7','8','9'}
multi[1] = {'a','b','c','d','e','f','g','h','i','j'}
multi[2] = {'A','B','C','D','E','F','G','H','I','J'}
multi[3] = {'9','8','7','6','5','4','3','2','1','0'}
multi[4] = {'J','I','H','G','F','E','D','C','B','A'} and contiguous memory would look like:
0123456789abcdefghijABCDEFGHIJ9876543210JIHGFEDCBA
^
|_____ starting at the address &multi[0][0] To access an element, pointer notation and array notation are equivalent:
*(*(multi + row) + col)
multi[row][col] Example:
------------------- program 6.1 ----------------------
/* Program 6.1 from PTRTUT10.HTM 6/13/97*/
#include <stdio.h>
#define ROWS 5
#define COLS 10
int multi[ROWS][COLS];
int main(void)
{
int row, col;
for (row = 0; row < ROWS; row++)
{
for (col = 0; col < COLS; col++)
{
multi[row][col] = row*col;
}
}
for (row = 0; row < ROWS; row++)
{
for (col = 0; col < COLS; col++)
{
printf("\n%d ",multi[row][col]);
printf("%d ",*(*(multi + row) + col));
}
}
return 0;
} Chapter 7: More on Multi-Dimensional Arrays
In the previous chapter we noted that given:
#define ROWS 5
#define COLS 10
int multi[ROWS][COLS]; we can access individual elements using either:
multi[row][col] or:
*(*(multi + row) + col) To understand more fully what is going on, let us replace *(multi + row) with X as in *(X + col). Here arithmetic on the pointer depends on the size of the thing pointed to.
To evaluate either form correctly, five things must be known: the address of the first element, the size of the element type, the second dimension of the array, and the specific values of row and col.
That is why, when writing a function to manipulate a two-dimensional array, the second dimension must appear in the parameter declaration:
void set_value(int m_array[][COLS])
{
int row, col;
for (row = 0; row < ROWS; row++)
{
for (col = 0; col < COLS; col++)
{
m_array[row][col] = 1;
}
}
} and the function is called as:
set_value(multi); In general, for multidimensional arrays, all dimensions of higher order than one are needed when dealing with function parameters.
Chapter 8: Pointers to Arrays
Pointers can be pointed at any type of data object, including arrays.
Given:
int *ptr;
ptr = &my_array[0]; we have a pointer to the first integer in an array.
For two-dimensional arrays, one way to make the type clearer is with typedef:
typedef unsigned char byte;
typedef int Array[10]; Then:
Array my_arr;
Array arr2d[5];
Array *p1d; Alternatively, without typedef:
int (*p1d)[10]; This is a pointer to an array of 10 integers. It is different from:
int *p1d[10]; which would be an array of 10 pointers to int.
Chapter 9: Pointers and Dynamic Allocation of Memory
There are times when it is convenient to allocate memory at run time using malloc(), calloc(), or other allocation functions.
int *iptr;
iptr = (int *)malloc(10 * sizeof(int));
if (iptr == NULL)
{
/* ERROR ROUTINE GOES HERE */
} Once assigned, array notation can still be used:
int k;
for (k = 0; k < 10; k++)
iptr[k] = 2; Method 1
#define COLS 5
typedef int RowArray[COLS];
RowArray *rptr;
int main(void)
{
int nrows = 10;
int row, col;
rptr = malloc(nrows * COLS * sizeof(int));
for (row = 0; row < nrows; row++)
{
for (col = 0; col < COLS; col++)
{
rptr[row][col] = 17;
}
}
return 0;
} Method 2
int (*xptr)[COLS]; Method 3
int main(void)
{
int nrows = 5;
int ncols = 10;
int row;
int **rowptr;
rowptr = malloc(nrows * sizeof(int *));
if (rowptr == NULL)
{
puts("\nFailure to allocate room for row pointers.\n");
exit(0);
}
printf("\n\n\nIndex Pointer(hex) Pointer(dec) Diff.(dec)");
for (row = 0; row < nrows; row++)
{
rowptr[row] = malloc(ncols * sizeof(int));
if (rowptr[row] == NULL)
{
printf("\nFailure to allocate for row[%d]\n", row);
exit(0);
}
printf("\n%d %p %d", row, rowptr[row], rowptr[row]);
if (row > 0)
printf(" %d", (int)(rowptr[row] - rowptr[row-1]));
}
return 0;
} Method 4
int main(void)
{
int **rptr;
int *aptr;
int *testptr;
int k;
int nrows = 5;
int ncols = 8;
int row, col;
aptr = malloc(nrows * ncols * sizeof(int));
if (aptr == NULL)
{
puts("\nFailure to allocate room for the array");
exit(0);
}
rptr = malloc(nrows * sizeof(int *));
if (rptr == NULL)
{
puts("\nFailure to allocate room for pointers");
exit(0);
}
for (k = 0; k < nrows; k++)
{
rptr[k] = aptr + (k * ncols);
}
printf("\n\nIllustrating how row pointers are incremented");
printf("\n\nIndex Pointer(hex) Diff.(dec)");
for (row = 0; row < nrows; row++)
{
printf("\n%d %p", row, rptr[row]);
if (row > 0)
printf(" %d", (rptr[row] - rptr[row-1]));
}
printf("\n\nAnd now we print out the array\n");
for (row = 0; row < nrows; row++)
{
for (col = 0; col < ncols; col++)
{
rptr[row][col] = row + col;
printf("%d ", rptr[row][col]);
}
putchar('\n');
}
puts("\n");
printf("And now we demonstrate that they are contiguous in memory\n");
testptr = aptr;
for (row = 0; row < nrows; row++)
{
for (col = 0; col < ncols; col++)
{
printf("%d ", *(testptr++));
}
putchar('\n');
}
return 0;
} As a final example, here is a three-dimensional allocation example:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
int X_DIM=16;
int Y_DIM=5;
int Z_DIM=3;
int main(void)
{
char *space;
char ***Arr3D;
int y, z;
ptrdiff_t diff;
space = malloc(X_DIM * Y_DIM * Z_DIM * sizeof(char));
Arr3D = malloc(Z_DIM * sizeof(char **));
for (z = 0; z < Z_DIM; z++)
{
Arr3D[z] = malloc(Y_DIM * sizeof(char *));
for (y = 0; y < Y_DIM; y++)
{
Arr3D[z][y] = space + (z*(X_DIM * Y_DIM) + y*X_DIM);
}
}
for (z = 0; z < Z_DIM; z++)
{
printf("Location of array %d is %p\n", z, *Arr3D[z]);
for (y = 0; y < Y_DIM; y++)
{
printf(" Array %d and Row %d starts at %p", z, y, Arr3D[z][y]);
diff = Arr3D[z][y] - space;
printf(" diff = %d ", diff);
printf(" z = %d y = %d\n", z, y);
}
}
return 0;
} Note that here space is a character pointer, which is the same type as Arr3D[z][y]. When assigning pointer values to pointer variables, the data types of the value and variable must match.
Chapter 10: Pointers to Functions
Up to this point we have been discussing pointers to data objects. C also permits the declaration of pointers to functions.
We will use a simple bubble sort for demonstration purposes.
/*-------------------- bubble_1.c --------------------*/
#include <stdio.h>
int arr[10] = { 3,6,1,2,3,8,4,1,7,2};
void bubble(int a[], int N);
int main(void)
{
int i;
putchar('\n');
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
bubble(arr,10);
putchar('\n');
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
void bubble(int a[], int N)
{
int i, j, t;
for (i = N-1; i >= 0; i--)
{
for (j = 1; j <= i; j++)
{
if (a[j-1] > a[j])
{
t = a[j-1];
a[j-1] = a[j];
a[j] = t;
}
}
}
} We can separate the comparison function, pass pointers to the values being compared, then generalize further with void * and a width parameter until the same sort routine can handle multiple data types.
int (*fptr)(const void *p1, const void *p2); That permits a universal bubble routine such as:
void bubble(void *p, int width, int N,
int(*fptr)(const void *, const void *)); Example with both long integers and strings:
/*------------------- bubble7.c ------------------*/
#include <stdio.h>
#include <string.h>
#define MAX_BUF 256
long arr[10] = { 3,6,1,2,3,8,4,1,7,2};
char arr2[5][20] = { "Mickey Mouse",
"Donald Duck",
"Minnie Mouse",
"Goofy",
"Ted Jensen" };
void bubble(void *p, int width, int N,
int(*fptr)(const void *, const void *));
int compare_string(const void *m, const void *n);
int compare_long(const void *m, const void *n);
int main(void)
{
int i;
puts("\nBefore Sorting:\n");
for (i = 0; i < 10; i++)
{
printf("%ld ",arr[i]);
}
puts("\n");
for (i = 0; i < 5; i++)
{
printf("%s\n", arr2[i]);
}
bubble(arr, 4, 10, compare_long);
bubble(arr2, 20, 5, compare_string);
puts("\n\nAfter Sorting:\n");
for (i = 0; i < 10; i++)
{
printf("%d ",arr[i]);
}
puts("\n");
for (i = 0; i < 5; i++)
{
printf("%s\n", arr2[i]);
}
return 0;
}
void bubble(void *p, int width, int N,
int(*fptr)(const void *, const void *))
{
int i, j, k;
unsigned char buf[MAX_BUF];
unsigned char *bp = p;
for (i = N-1; i >= 0; i--)
{
for (j = 1; j <= i; j++)
{
k = fptr((void *)(bp + width*(j-1)), (void *)(bp + j*width));
if (k > 0)
{
memcpy(buf, bp + width*(j-1), width);
memcpy(bp + width*(j-1), bp + j*width , width);
memcpy(bp + j*width, buf, width);
}
}
}
}
int compare_string(const void *m, const void *n)
{
char *m1 = (char *)m;
char *n1 = (char *)n;
return (strcmp(m1,n1));
}
int compare_long(const void *m, const void *n)
{
long *m1, *n1;
m1 = (long *)m;
n1 = (long *)n;
return (*m1 > *n1);
} References for Chapter 10
- "Algorithms in C"
Robert Sedgewick
Addison-Wesley
ISBN 0-201-51425-7
Discuss this article in the forums
Date this article was posted to GameDev.net: 2/17/2002
Note that this date does not necessarily correspond to the date the article was written.
See Also:
C and C++
Related Tutorials
Balancing Game Development and Creative Direction in Indie Production
A practical look at how indie developers can balance creative direction with hands-on game development. This article co…
My Unreal Engine Development Process: From Core Idea to Playable Build
A practical overview of my Unreal Engine development process, covering how I move from a core game idea to a playable b…
Introducing LaneGraph: The Ultimate Road Network Solution for Unity
Discover the power of LaneGraph, a lightweight and flexible lane-based navigation system for Unity. LaneGraph makes it…
Retargeting Mixamo Characters with Root Motion In Unreal Engine 5.4.
I have always found Retargeting Mixamo Characters To have Root Motion is a serious lengthy Tast, Recently I stumbled up…
How To Make A SIMPLE Main Menu In Unity
In this tutorial for unity, i go over how to make a simple main menu for unity, it's an unlisted video because i do not…
Guide to Gameplay Balance
A perspective on competitive gameplay balance, from a background of "shooter" sandbox design.
Discussion
More from Ted Jensen
Comparing Shadow Mapping Techniques with Shadow Explorer
New Incentives and a Whole New Platform From The Intel AppUp developer program
The final installment in this series on Intel's AppUp program details additional incentives and opportunities for devel…
The Game Maker
This book excerpt contains the first chapter of the book that introduces beginning game developers to the Game Maker pr…
Discussion