How C Programming Works?
The C
programming language is incredibly popular, and it's easy to see why.
Programming in C is efficient and gives the programmer a great deal of control.
Many other programming languages like C++, Java and Python were developed using
C.
The C programming language gives you more
versatility than many other languages, including greater control over your
computer's memory.
Chances
are increasing each day that if you're a programmer, you won't use C
exclusively for your work. However, there are several learning C is highly
beneficial, even if you don't use it regularly. Here's why:
You'll
be able to read and write code for software that can be used on many different
types of computer platforms, including everything from small microcontrollers
to desktop, laptop and mobile operating systems.
You'll
better understand what high-level languages are doing behind the scenes, such
as memory management and garbage collection. This understanding can help you
write programs that work more efficiently.
If
you're an information technology (IT) specialist, you could also benefit from
learning C. IT professionals often write, maintain and run scripts as part of
their job. A script is a list of instructions for a
computer's operating system to follow. To run certain scripts, the computer
sets up a controlled execution environment called ashell.
Since most operating systems run shells based on C, C shell is a popular scripting adaptation of C
used by IT pros.
This
article covers the history behind C, looks at why C is so important, shows
examples of some basic C code and explores some important features of C,
including data types, operations, functions, pointers and memory management.
Though this article isn't an instruction manual for programming in C, it does
cover what makes C programming unique in a way that goes beyond those first few
chapters of the average C programming guide.
Let's
start by looking at where the C programming language came from, how it has
developed and the role it has in software development today.
What is
C?
The
simplest way to define C is to call it a computer programming language, meaning
you can write software with it that a computer can execute. The result could be
a large computer application, like your Web browser, or a tiny set of
instructions embedded in a microprocessor or other computer component.
The
language C was developed in the early 1970s at Bell Laboratories, primarily
credited to the work of Ken Thompson and Dennis Ritchie. Programmers needed a
more user-friendly set of instructions for the UNIX operating system, which at
the time required programs written in assembly language. Assembly programs,
which speak directly to a computer's hardware, are long and difficult to debug,
and they required tedious, time-consuming work to add new features [source:
King].
Thompson's
first attempt at a high-level language was called B, a tribute to the system
programming language BCPL on which it was based. When Bell Labs acquired a
Digital Equipment Corporation (DEC) UNIX system model PDP-11, Thompson reworked
B to better fit the demands of the newer, better system hardware. Thus, B's
successor, C, was born. By 1973, C was stable enough that UNIX itself could be
rewritten using this innovative new higher-level language [source: King].
Before
C could be used effectively beyond Bell Labs, other programmers needed a
document that explained how to use it. In 1978, the book "The C
Programming Language" by Brian Kernighan and Dennis Ritchie, known by C
enthusiasts as K&R or the "White Book," became the definitive
source for C programming. As of this writing, the second edition of K&R,
originally published in 1988, is still widely available. The original,
pre-standard version of C is called K&R C based on that book.
To
ensure that people didn't create their own dialects over time, C developers
worked through the 1980s to create standards for the language. The U.S.
standard for C, American National Standards Institute (ANSI) standard
X3.159-1989, became official in 1989. The International Organization for
Standardization (ISO) standard, ISO/IEC 9899:1990, followed in 1990. The versions
of C after K&R reference these standards and their later revisions (C89,
C90 and C99). You might also see C89 referred to as "ANSI C,"
"ANSI/ISO C" or "ISO C."
C and
its use in UNIX was just one part of the boom in operating system development
through the 1980s. For all its improvements over its predecessors, though, C
was still not effortless to use for developing larger software applications. As
computers became more powerful, demand increased for an easier programming
experience. This demand prompted programmers to build their own compilers, and
thus their own new programming languages, using C. These new languages could
simplify coding complex tasks with lots of moving parts. For example, languages
like C++ and Java, both developed from C, simplified object-oriented
programming, a programming approach that optimizes a programmer's ability to
reuse code.
Now
that you know a little background, let's look at the mechanics of C itself.
Editing
and Compiling C Code
C is
what's referred to as a compiled language, meaning you have to use a compiler
to turn the code into an executable file before you can run it. The code is
written into one or more text files, which you can open, read and edit in any
text editor, such as Notepad in Windows, TextEdit on a Mac, and gedit in Linux.
An executable file is something the computer can run (execute). The compiler
checks the code for errors and, if it seems to be error-free, creates an
executable file.
Before
we look at what goes into the C code, let's be sure we can find and use a C
compiler. If you're using Mac OS X and most Linux distributions (such as
Ubuntu), you can add a C compiler to your computer if you install the
development tools software for that particular OS. These free C compilers are
command line tools, which means you'll typically run them from a command prompt
in a terminal window. The command to run one of these C compilers is
"cc" or "gcc" plus some command line options and arguments,
which are other words typed after the command before you press Enter.
If
you're using Microsoft Windows, or you would prefer to use a graphical user
interface rather than a command line, you can install an integrated development
environment (IDE) for C programming. An IDE is a single interface where you can
write your code, compile it, test it and quickly find and fix errors. For
Windows, you could purchase Microsoft Visual C++ software, an IDE for both C
and C++ programming. Another popular IDE is Eclipse, a free Java-based IDE that
runs on Windows, Mac and Linux and has extensions available for compiling C and
many other programming languages.
For C,
as for other computer programming languages, the version of the compiler you
use is very important. You always want to use a version of the C compiler
that's as new or newer than the version of the C language you're using in your
program. If you're using an IDE, be sure to adjust your settings to make sure
the IDE is using your target C version for the program you're working on. If
you're at a command line, you can add a command line argument to change the
version as in the following command:
gcc
–std c99 –o myprogram.exe myprogram.c
In the
command above, "gcc" is the call to run the compiler and everything
else is a command line option or argument. The "-std" option was
added followed by "c99" to tell the compiler to use the C99 standard
version of C during its compiling. The "-o" option was added followed
by "myprogram.exe" to request that the executable, the compiler's
output file, to be named myprogram.exe. Without "-o" the executable
is automatically named a.out instead. The final argument
"myprogram.c" indicates the text file with the C code to be compiled.
In short, this command is saying, "Hey, gcc, compile myprogram.c using the
C99 C programming standard and put the results in a file named
myprogram.exe." Browse the Web for a complete list of options you can use
with your particular compiler, whether it's gcc or something else.
With
your compiler installed, you're ready to program in C. Let's start by taking a
look at the basic structure of one of the simplest C programs you could write.
The
Simplest C Program
Let's
look at a simple C program and use it both to understand the basics of C and
the C compilation process. If you have your own computer with a C compiler
installed as described earlier, you can create a text file named sample.c and
use it to follow along while we step through this example. Note that if you
leave off the .c in the file name, or if your editor appends .txt to the name,
you'll probably get some sort of error when you compile it.
Here's
our sample program:
/*
Sample program */
#include
<stdio.h>
int
main()
{
printf("This
is output from my first program!\n");
return
0;
}
When
compiled and executed, this program instructs the computer to print out the
line "This is output from my first program!" and then stop. You can't
get much simpler than that! Now let's take a look at what each line is doing:
Line 1
-- This is one way to write comments in C, between /* and */ on one or more
lines.
Line 2
-- The #include command tells the compiler to look at other sources for
existing C code, particularly libraries, which are files that include common
reusable instructions. The references a standard C library with functions for
getting input from a user and for writing output to the screen. We'll look at
libraries a more closely later.
Line 3
-- This line the first line of a function definition. Every C program has at
least one function, or a block of code representing something the computer
should do when the program runs. The function performs its task and then
produces a byproduct, called a return value, that can be used by other
functions. At a minimum, the program has a function called main like the one
shown here with a return value with the data type int, which means integer.
When we examine functions more later, you'll see what the empty parentheses
mean.
Lines 4
and 7 -- The instructions within a function are enclosed in braces. Some
programmers start and end a brace-enclosed block on separate lines as shown
here. Others will put the open-brace ({) at the end of the first line of the
function definition. Though lines of code in the program don't have to be typed
on separate lines, programmers typically put each instruction on a separate
line, indented with spaces, to make the code easier to read and edit later.
Line 5
-- This is a function call to a function named printf. That function is coded
in the stdio.h library included from Line 1, so you don't have to write it
yourself. This call to printf tells it what to print to the screen. The \n at
the end, within the quotes, isn't printed, though; it's an escape sequence
which instructs printf to move the cursor to the next line on the screen. Also,
as you can see, every line in the function must end with a semi-colon.
Line 6
-- Every function that returns a value must include a return statement like
this one. In C, the main function must always have an integer return type, even
though it's not used within the program. Note that when you're running a C
program, though, you're essentially running its main function. So, when you're
testing the program, you can tell the computer to show the return value from
running the program. A return value of 0 is preferred since programmers
typically look for that value in testing to confirm the program ran
successfully.
When
you're ready to test your program, save the file and compile and run the
program. If you're using the gcc compiler at a command line, and the program is
in a file called sample.c, you can compile it with the following command:
gcc -o
sample.exe sample.c
If
there are no errors in the code, you should have a file named sample.exe in the
same directory as sample.c after running this command. The most common error is
a syntax error, meaning that you've mistyped something, such as leaving off a
semicolon at the end of a line or not closing quotes or parentheses. If you
need to make changes, open the file in your text editor, fix it, save your
changes and try your compile command again.
To run
the sample.exe program, enter the following command. Note the ./ which forces
the computer to look at the current directory to find the executable file:
./sample.exe
Those
are the basics of coding and compiling for C, though there's a lot more you can
learn about compiling from other C programming resources. Now, let's open the
box and see what pieces C has for building programs.
Common
Programming Concepts in C
Let's
take a look at how to put some of the common programming concepts into practice
in your C code. The following is a quick summary of these concepts:
Functions -- As
stated earlier, a function is a block of code representing something the computer
should do when the program runs. Some languages call these structures methods,
though C programmers don't typically use that term. Your program may define
several functions and call those functions from other functions. Later, we'll
take a closer look at the structure of functions in C.
Variables -- When
you run a program, sometimes you need the flexibility to run the program
without knowing what the values are ahead of time. Like other programming
languages, C allows you to use variables when you need that flexibility. Like
variables in algebra, a variable in computer programming is a placeholder that
stands for some value that you don't know or haven't found yet.
Data types -- In
order to store data in memory while your program is running, and to know what
operations you can perform on that data, a programming language like C defines
certain data types it will recognize. Each data type in C has a certain size,
measured in binary bits or bytes, and a certain set of rules about what its
bits represent. Coming up, we'll see how important it is choose the right data
type for the task when you're using C.
Operations -- In
C, you can perform arithmetic operations (such as addition) on numbers and
string operations (such as concatenation) on strings of characters. C also has
built-in operations specifically designed for things you might want to do with
your data. When we check out data types in C, we'll take a brief look at the
operations, too.
Loops -- One
of the most basic things a programmer will want to do is repeat an action some
number of times based on certain conditions that come up while the program is
running. A block of code designed to repeat based on given conditions is called
a loop, and the C language provides for these common loop structures: while,
do/while, for, continue/break and goto. C also includes the common if/then/else
conditionals and switch/case statements.
Data structures -- When your program has a lot of data to
handle, and you need to sort or search through that data, you'll probably use
some sort of data structure. A data structure is a structured way of
representing several pieces of data of the same data type. The most common data
structure is an array, which is just an indexed list of a given size. C has
libraries available to handle some common data structures, though you can
always write functions and set up your own structures, too.
Preprocessor operations -- Sometimes you'll want to give the
compiler some instructions on things to do with your code before compiling it
into the executable. These operations include substituting constant values and
including code from C libraries (which you saw in the sample code earlier).
C also
requires programmers to handle some concepts which many programming languages
have simplified or automated. These include pointers, memory management, and
garbage collection. Later pages cover the important things to know about these
concepts when programming in C.
This
quick overview of concepts may seem overwhelming if you're not already a
programmer. Before you move on to tackle a dense C programming guide, let's
take a user-friendly look at the core concepts among those listed above,
starting with functions.
Functions
in C
Most
computer programming languages allow you to create functions of some sort.
Functions let you chop up a long program into named sections so that you can
reuse those sections throughout the program. Programmers for some languages,
especially those using object-oriented programming techniques, use the term method instead of function.
Functions
accept parameters and return a result. The block of code that comprises a
function is its function definition. The following is the basic structure of a
function definition:
<return
type> <function name>(<parameters>)
{
<statements>
return
<value appropriate for the return type>;
}
At a
minimum, a C program has one function named main. The compiler will look for a
main function as the starting point for the program, even if the main function
calls other functions within it. The following is the main we saw in the simple
C program we looked at before. It has a return type of integer, takes no
parameters, and has two statements (instructions within the function), one of
which is its return statement:
int
main()
{
printf("This
is output from my first program!\n");
return
0;
}
Functions
other than main have a definition and one or more function calls. A function
call is a statement or part of a statement within another function. The
function call names the function it's calling followed by parentheses. If the
function has parameters, the function call must include corresponding values to
match those parameters. This additional part of the function call is called
passing parameters to the function.
But
what are parameters? A parameter for a function is a piece of data of a certain
data type that the function requires to do its work. Functions in C can accept
an unlimited number of parameters, sometimes called arguments. Each parameter
added to a function definition must specify two things: its data type and its
variable name within the function block. Multiple parameters are be separated
by a comma. In the following function, there are two parameters, both integers:
int
doubleAndAdd(int a, int b)
{
return
((2*a)+(2*b));
}
Next,
let's continue our look at functions by zooming out to look at how they fit
within a larger C program.
FUNCTION DECLARATIONS
In C,
you'll probably hear the term function declaration more than function
prototype, especially among older C programmers. We're using the term function
prototype in this article, though, because it has an important distinction.
Originally, a function declaration did not require any parameters, so the
return type, function name and a pair of empty parentheses were sufficient. A
function prototype, though, gives the compiler important additional information
by including the number and data types of the parameters it will call.
Prototypes have become a best practice approach among coders today, in C and
other programming languages.
Function Prototypes
In C,
you can add a function definition anywhere within the program (except within
another function). The only condition is that you must tell the compiler in
advance that the function exists somewhere later in the code. You'll do this
with a function prototype at the beginning of the program. The prototype is a
statement that looks similar to the first line of the definition. In C, you
don't have to give the names of the parameters in the prototype, only the data
types. The following is what the function prototype would look like for the
doubleAndAdd function:
int
doubleAndAdd(int, int);
Imagine
function prototypes as the packing list for your program. The compiler will
unpack and assemble your program just as you might unpack and assemble a new
bookshelf. The packing list helps you ensure you have all the pieces you need
in the box before you start assembling the bookshelf. The compiler uses the
function prototypes in the same way before it starts assembling your program.
If
you're following along with the sample.c program we looked at earlier, open and
edit the file to add a function prototype, function definition and function
call for the doubleAndAdd function shown here. Then, compile and run your
program as before to see how the new code works. You can use the following code
as a guide to try it out:
#include
<stdio.h>
int
doubleAndAdd(int, int);
int
main()
{
printf("This
is output from my first program!\n");
printf("If
you double then add 2 and 3, the result is: %d \n", doubleAndAdd(2,3));
return
0;
}
int
doubleAndAdd(int a, int b)
{
return
((2*a)+(2*b));
}
So far
we've looked at some basic structural elements in a C program. Now, let's look
at the types of data you can work with in a C program and what operations you
can perform on that data.
Data
Types and Operations in C
From your computer's point of view, your program is all just a series of ones and zeros. Data types in C tell the computer how to use some of those bits.
From your computer's perspective, data is
nothing but a series of ones and zeros representing on and off states for the
electronic bits on your hard drive or in your computer's processor or memory.
It's the software you're running on a computer that determines how to make
sense of those billions of binary digits. C is one of few high-level languages
that can easily manipulate data at the bit level in addition to interpreting
the data based on a given data type.
A data
type is a small set of rules that indicate how to make sense of a series of
bits. The data type has a specific size plus its own way of performing
operations (such as adding and multiplying) on data of that type. In C, the
size of the data type is related to the processor you're using. For example, in
C99, a piece of data of the integer data type (int) is 16 bits long in a 16-bit
processor while for 32-bit and 64-bit processors it's 32 bits long.
Another
important thing for C programmers to know is how the language handles signed
and unsigned data types. A signed type means that one of its bits is reserved
as the indicator for whether it's a positive or negative number. So, while an
unsigned int on a 16-bit system can handle numbers between 0 and 65,535, a
signed in on the same system can handle numbers between -32,768 and 32,767. If
an operation causes an int variable to go beyond its range, the programmer has
to handle the overflow with additional code.
Given
these constraints and system-specific peculiarities in C data types and
operations, C programmers must choose their data types based on the needs of
their programs. Some of the data types they can choose are the primitive data
types in C, meaning those built in to the C programming language. Look to your
favorite C programming guide for a complete list of the data types in C and
important information about how to convert data from one type to another.
C
programmers can also create data structures, which combine primitive data types
and a set of functions that define how the data can be organized and manipulated.
Though the use of data structures is an advanced programming topic and beyond
the scope of this article, we will take a look at one of the most common
structures: arrays. An array is a virtual list containing pieces of data that
are all the same data type. An array's size can't be changed, though its
contents can be copied to other larger or smaller arrays.
Though
programmers often use arrays of numbers, character arrays, called strings, have
the most unique features. A string allows you to save something you might say
(like "hello") into a series of characters, which your C program can
read in from the user or print out on the screen. String manipulation has such
a unique set of operations, it has its own dedicated C library (string.h) with
your typical string functions.
The
built-in operations in C are the typical operations you'd find in most
programming languages. When you're combining several operations into a single
statement, be sure to know the operator precedence, or the order in which the program
will perform each operation in a mathematical expression. For example, (2+5)*3
equals 21 while 2+5*3 equals 17, because C will perform multiplication before
addition unless there are parentheses indicating otherwise.
If
you're learning C, make it a priority to familiarize yourself with all of its
primitive data types and operations and the precedence for operations in the
same expression. Also, experiment with different operations on variables and
numbers of different data types.
At this
point, you've scratched the surface of some important C basics. Next, though,
let's look at how C enables you to write programs without starting from scratch
every time.
Don't Start from Scratch, Use Libraries
Libraries
are very important in C because the C language supports only the most basic
features that it needs. For example, C doesn't contain input-output (I/O)
functions to read from the keyboard and write to the screen. Anything that
extends beyond the basics must be written by a programmer. If the chunk of code
is useful to multiple different programs, it's often put into a library to make
it easily reusable.
In our
discussion of C so far, we've already seen one library, the standard I/O
(stdio) library. The #include line at the beginning of the program instructed
the C compiler to loaded the library from its header file named stdio.h. C
maintainers include standard C libraries for I/O, mathematical functions, time
manipulation and common operations on certain data structures, such as a string
of characters. Search the Web or your favorite C programming guide for information
about the C89 standard library and the updates and additions in C99.
You,
too, can write C libraries. By doing so, you can split your program into
reusable modules. This modular approach not only makes it easy to include the
same code in multiple programs, but it also makes for shorter program files
which are easier to read, test and debug.
To use
the functions within a header file, add a #include line for it at the beginning
of your program. For standard libraries, put the name of the library's corresponding
header file between greater-than and less-than signs (). For libraries you
create yourself, put the name of the file between double quotes. Unlike
statements in other parts of your C program, you don't have to put a semicolon
at the end of each line. The following shows including one of each type of
library:
#include
<math.h>
#include
"mylib.h"
A
comprehensive C programming source should provide the instructions you need to
write your own libraries in C. The function definitions you'll write are not
any different whether they're in a library or in your main program. The
difference is that you'll compile them separately in something called an object
file (with a name ending in .o), and you'll create a second file, called a
header file (with a name ending in .h) which contains the function prototypes
corresponding to each function in the library. It's the header file you'll
reference in your #include line in each main program that uses your library,
and you'll include the object file as an argument in the compiler command each
time you compile that program.
The C
features we've explored so far are typical in other programming languages, too.
Next, though, we'll talk about how C manages your computer's memory.
Some
Pointers about Pointers in C
When your
C program is loaded into memory (typically the random-access memory, or RAM, in
your computer), each piece of the program is associated with an address in
memory. This includes the variables you're using to hold certain data. Each
time your program calls a function, it loads that function and all of its
associated data into memory just long enough to run that function and return a
value. If you pass parameters to the function, C automatically makes a copy of
the value to use in the function.
Sometimes
when you run a function, though, you want to make some permanent change to the
data at its original memory location. If C makes a copy of data to use in the
function, the original data remains unchanged. If you want to change that
original data, you have to pass a pointer to its memory address (pass by
reference) instead of passing its value to the function (pass by value).
Pointers
are used everywhere in C, so if you want to use the C language fully you have
to have a good understanding of pointers. A pointer is a variable like other
variables, but its purpose is to store the memory address of some other data.
The pointer also has a data type so it knows how to recognize the bits at that
memory address.
When
you look at two variables side-by-side in C code, you may not always recognize
the pointer. This can be a challenge for even the most experienced C
programmers. When you first create a pointer, though, it's more obvious because
there must be an asterisk immediately before the variable name. This is known as
the indirection operator in C. The following example code creates an integer i
and a pointer to an integer p:
int i;
int *p;
Currently
there is no value assigned to either i or p. Next, let's assign a value to i
and then assign p to point to the address of i.
i = 3;
p =
&i;
Here
you can see the ampersand (&) used as the address operator immediately
before i, meaning the "address of i." You don't have to know what
that address is to make the assignment. That's good, because it will likely be
different every time you run the program! Instead, the address operator will
determine the address associated with that variable while the program is
running. Without the address operator, the assignment p=i would assign p the
memory address of 3, literally, rather than the memory address of the variable
i.
Next,
let's look at how you can use pointers in C code and the challenges you'll want
to be prepared for.
Using
Pointers Correctly in C
If you want to become proficient in C programming, you'll need a firm grasp of how to effectively use pointers in your code.
Once you have a pointer, you can use that
in place of a variable of the same data type in operations and function calls.
In the following example, the pointer to i is used instead of i within a larger
operation. The asterisk used with the p (*p) indicates that the operation
should use the value that p is pointing to at that memory address, not the
memory address itself:
int b;
b = *p
+ 2;
Without
pointers, it's nearly impossible to divide tasks into functions outside of main
in your C program. To illustrate this, consider you've created a variable in
main called h that stores the user's height to the nearest centimeter. You also
call a function you've written named setHeight that prompts the user to set
that height value. The lines in your main function might look something like
this:
int h;
setHeight(h);
/* There is a potential problem here. */
This
function call will try to pass the value of h to setHeight. However, when the
function finishes running, the value of h will be unchanged because the
function only used a copy of it and then discarded it when it finished running.
If you
want to change h itself, you should first ensure that the function can take a
pointer to an existing value rather than a new copy of a value. The first line
of setHeight, then, would use a pointer instead of a value as its parameter
(note the indirection operator):
setHeight(int
*height) { /* Function statements go here */ }
Then,
you have two choices for calling setHeight. The first is to use the address
operator for h as the passed parameter (&h). The other is to create a
separate pointer to h and pass that instead. The following shows both options:
setHeight(&h);
/* Pass the address of h to the function */
int *p;
p =
&h;
setHeight(p);
/* Pass a separate pointer to the address of h to the function */
The
second option reveals a common challenge when using pointers. The challenge is
having multiple pointers to the same value. This means that any change in that
one value affects all its pointers at once. This could be a good or bad thing,
depending on what you're trying to accomplish in your program. Again, mastering
the use of pointers is an important key to mastering C programming. Practice
with pointers as much as possible so you'll be ready to face these challenges.
The C
features we've explored so far are typical in other programming languages, too.
Next, though, we'll look at C's demands for careful memory management.
The
Importance of Memory Management in C
To better understand the importance of memory
management, consider how a program uses memory. When you first run a program,
it loads into your computer's memory and begins to execute by sending and
receiving instructions from the computer's processor. When the program needs to
run a particular function, it loads that function into yet another part of
memory for the duration of its run, then abandons that memory when the function
is complete. Plus, each new piece of data used in the main program takes up
memory for the duration of the program.
If you want more control over all this, you
need dynamic storage allocation. C supports dynamic storage allocation, which
is the ability to reserve memory as you need it and free that memory as soon as
you're finished using it. Many programming languages have automatic memory
allocation and garbage collection that handle these memory management tasks. C,
though, allows (and in some cases requires) you to be explicit about memory
allocation with the following key functions from the standard C library:
·
malloc -- Short for
memory allocation, malloc is used to reserve a block of memory of a given size to story a
certain type of data your program needs to process. When you use malloc, you're
creating a pointer to the allocated memory. This isn't necessary for a single
piece of data, such as one integer, which is allocated as soon as you first
declare it (as in int i). However, it is an important part of creating and
managing data structures such as arrays. Alternate memory allocation options in
C are calloc, which also clears the memory when it's
reserved, and realloc, which resizes previously reserved memory.
·
free -- Use free to force
your program to free the memory previously assigned to a given pointer.
Best practice when using malloc and free is
that anything you allocate should be freed. Whenever you allocate something,
even in a temporary function, it remains in memory until the operating system
cleans up the space. To ensure that memory is free and ready to use
immediately, though, you should free it before the current function exits. This
memory management means you can keep your program's memory footprint to a
minimum and avoid memory leaks. A memory leak is a program flaw in which it
continues using more and more memory until there's none left to allocate,
causing the program to stall or crash. On the other hand, don't get so anxious
about freeing memory that you free up, and thus lose, something that you need
later in the same function.
Throughout this article, you've learned some
of the basic structure and core concepts of the C programming language. We've
looked at its history, the characteristics it has in common with other
programming languages and the important features that make it a unique and
versatile option for coding software. Launch over to the next page for lots
more information, including some programming guides that will carry you further
on your journey into C.