Professional Documents
Culture Documents
C Pointers
In this tutorial, you'll learn about pointers; what pointers are, how do you use them and the
common mistakes you might face when working with them with the help of examples.
Pointers are powerful features of C and C++ programming. Before we learn pointers, let's
learn about addresses in C programming.
Address in C
If you have a variable var in your program, &var will give you its address in the memory.
We have used address numerous times while using the scanf() function.
scanf("%d", &var);
Here, the value entered by the user is stored in the address of var variable. Let's take a
working example.
#include <stdio.h>
int main()
{
int var = 5;
printf("var: %d\n", var);
var: 5
address of var: 2686778
Note: You will probably get a different address when you run the above code.
C Pointers
Pointers (pointer variables) are special variables that are used to store addresses rather than
values.
Pointer Syntax
int* p;
int *p1;
int * p2;
int* pc, c;
c = 5;
pc = &c;
Here, 5 is assigned to the c variable. And, the address of c is assigned to the pc pointer.
To get the value of the thing pointed by the pointers, we use the * operator. For example:
int* pc, c;
c = 5;
pc = &c;
printf("%d", *pc); // Output: 5
Here, the address of c is assigned to the pc pointer. To get the value stored in that address,
we used *pc.
Note: In the above example, pc is a pointer, not *pc. You cannot and should not do
something like *pc = &c;
By the way, * is called the dereference operator (when working with pointers). It operates on
a pointer and gives the value stored in that pointer.
int* pc, c;
c = 5;
pc = &c;
c = 1;
printf("%d", c); // Output: 1
printf("%d", *pc); // Ouptut: 1
int* pc, c;
c = 5;
pc = &c;
*pc = 1;
printf("%d", *pc); // Ouptut: 1
printf("%d", c); // Output: 1
int* pc, c, d;
c = 5;
d = -15;
Initially, the address of c is assigned to the pc pointer using pc = &c;. Since c is 5, *pc gives
us 5.
Then, the address of d is assigned to the pc pointer using pc = &d;. Since d is -15, *pc gives
us -15.
#include <stdio.h>
int main()
{
int* pc, c;
c = 22;
printf("Address of c: %p\n", &c);
printf("Value of c: %d\n\n", c); // 22
pc = &c;
printf("Address of pointer pc: %p\n", pc);
printf("Content of pointer pc: %d\n\n", *pc); // 22
c = 11;
printf("Address of pointer pc: %p\n", pc);
printf("Content of pointer pc: %d\n\n", *pc); // 11
*pc = 2;
printf("Address of c: %p\n", &c);
printf("Value of c: %d\n\n", c); // 2
return 0;
}
Output
Address of c: 2686784
Value of c: 22
Address of c: 2686784
Value of c: 2
Explanation of the program
1. int* pc, c;
2. c = 22;
This assigns 22 to the variable c. That is, 22 is stored in the memory location of variable c.
3. pc = &c;
4. c = 11;
This assigns 11 to variable c.
5. *pc = 2;
This change the value at the memory location pointed by the pointer pc to 2.
int c, *pc;
printf("%d", *p); // 5
return 0;
}
int *p = &c;
is equivalent to
int *p:
p = &c;
In both cases, we are creating a pointer p (not *p) and assigning &c to it.
To avoid this confusion, we can use the statement like this:
int* p = &c;
Now you know what pointers are, you will learn how pointers are related to arrays in the next
tutorial.
So far the operations using the C program are done on a prompt/terminal which is not stored
anywhere. But in the software industry, most programs are written to store the information
fetched from the program. One such way is to store the fetched information in a file. Different
operations that can be performed on a file are:
1. Creation of a new file (fopen() with attributes as “a” or “a+” or “w” or “w+”)
2. Opening an existing file (fopen())
3. Reading from file (fscanf() or fgets())
4. Writing to a file (fprintf() or fputs())
5. Moving to a specific location in a file (fseek(), rewind())
6. Closing a file (fclose())
The text in the brackets denotes the functions used for performing those operations.
In order to understand why file handling makes programming easier, let us look at a few
reasons:
Reusability: The file-handling process keeps track of the information created after the
program has been run.
Portability: Without losing any data files can be transferred to another in the computer
system. The risk of flawed coding is minimized with this feature.
Efficient: A large amount of input may be required for some programs. File handling
allows you to easily access a part of a code using individual commands which saves a
lot of time and reduces the chance of errors.
Storage Capacity: Files allow you to store data without having to worry about storing
everything simultaneously in a program.
Types of Files in C
Generally, a text file contains alphabets, digits, and special characters or symbols, while a
binary file contains bytes or a compiled version of the text. It is important to recognize two
types of files when dealing with files:
Text Files
Binary Files
Text Files: Text files contain data in the form of ASCII characters and are generally used
to store a stream of characters. Each line in a text file ends with a new line character (‘/n’).
Text files are used to store the source code.
Binary Files: Binary files contain data that is stored in a similar manner to how it is stored
in the main memory. Instead of ASCII characters, it is stored in binary format. The binary
files can be created only from within a program and their contents can only be read by a
program.
For opening a file, fopen() function is used with the required access modes. Some of the
commonly used file access modes are mentioned below.
Searches file. If the file is opened successfully fopen( ) loads it into memory
and sets up a pointer that points to the first character in it. If the file cannot
R be opened fopen( ) returns NULL.
Open for reading in binary mode. If the file does not exist, fopen( ) returns
Rb NULL.
Searches file. If the file exists, its contents are overwritten. If the file doesn’t
W exist, a new file is created. Returns NULL, if unable to open the file.
Open for writing in binary mode. If the file exists, its contents are
wb overwritten. If the file does not exist, it will be created.
Searches file. If the file is opened successfully fopen( ) loads it into memory
and sets up a pointer that points to the last character in it. If the file doesn’t
A exist, a new file is created. Returns NULL, if unable to open the file.
Open for append in binary mode. Data is added to the end of the file. If the
Ab file does not exist, it will be created.
Searches file. It is opened successfully fopen( ) loads it into memory and sets
up a pointer that points to the first character in it. Returns NULL, if unable to
r+ open the file.
Open for both reading and writing in binary mode. If the file does not exist,
rb+ fopen( ) returns NULL.
Opening
Modes Description
Searches file. If the file exists, its contents are overwritten. If the file doesn’t
w+ exist a new file is created. Returns NULL, if unable to open the file.
Open for both reading and writing in binary mode. If the file exists, its
wb+ contents are overwritten. If the file does not exist, it will be created.
Searches file. If the file is opened successfully fopen( ) loads it into memory
and sets up a pointer that points to the last character in it. If the file doesn’t
a+ exist, a new file is created. Returns NULL, if unable to open the file.
Open for both reading and appending in binary mode. If the file does not
ab+ exist, it will be created.
As given above, if you want to perform operations on a binary file, then you have to append
‘b’ at the last. For example, instead of “w”, you have to use “wb”, instead of “a+” you have
to use “a+b”. For performing the operations on the file, a special pointer called File pointer
is used which is declared as:
FILE *filePointer;
The second parameter can be changed to contain all the attributes listed in the above table.
FILE * filePointer;
Writing to a File
The file write operations can be performed by the functions fprintf and fputs with similarities
to read operations. The snippet for writing to a file is as:
FILE *filePointer ;
Closing a File
After every successful file operation, you must always close a file. For closing a file, you
have to use fclose() function. The snippet for closing a file is given as:
FILE *filePointer ;
fclose(filePointer)
Functions Description
The C Preprocessor is not a part of the compiler, but is a separate step in the compilation
process. In simple terms, a C Preprocessor is just a text substitution tool and it instructs the
compiler to do required pre-processing before the actual compilation. We'll refer to the C
Preprocessor as CPP.
All preprocessor commands begin with a hash symbol (#). It must be the first nonblank
character, and for readability, a preprocessor directive should begin in the first column. The
following section lists down all the important preprocessor directives −
1
#define
2
#include
3
#undef
4
#ifdef
6
#if
7
#else
8
#elif
9
#endif
10
#error
11
#pragma
Preprocessors Examples
#define MAX_ARRAY_LENGTH 20
This directive tells the CPP to replace instances of MAX_ARRAY_LENGTH with 20.
Use #define for constants to increase readability.
#include <stdio.h>
#include "myheader.h"
These directives tell the CPP to get stdio.h from System Libraries and add the text to the
current source file. The next line tells CPP to get myheader.h from the local directory and add
the content to the current source file.
#undef FILE_SIZE
#define FILE_SIZE 42
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
It tells the CPP to define MESSAGE only if MESSAGE isn't already defined.
#ifdef DEBUG
/* Your debugging statements here */
#endif
It tells the CPP to process the statements enclosed if DEBUG is defined. This is useful if you
pass the -DDEBUG flag to the gcc compiler at the time of compilation. This will define
DEBUG, so you can turn debugging on and off on the fly during compilation.
Predefined Macros
ANSI C defines a number of macros. Although each one is available for use in programming,
the predefined macros should not be directly modified.
1
__DATE__
3
__FILE__
4
__LINE__
5
__STDC__
Live Demo
#include <stdio.h>
int main() {
When the above code in a file test.c is compiled and executed, it produces the following result
−
File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1
Preprocessor Operators
A macro is normally confined to a single line. The macro continuation operator (\) is used to
continue a macro that is too long for a single line. For example −
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
The Stringize (#) Operator
The stringize or number-sign operator ( '#' ), when used within a macro definition, converts a
macro parameter into a string constant. This operator may be used only in a macro having a
specified argument or parameter list. For example −
Live Demo
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void) {
message_for(Carole, Debra);
return 0;
}
When the above code is compiled and executed, it produces the following result −
The token-pasting operator (##) within a macro definition combines two arguments. It permits
two separate tokens in the macro definition to be joined into a single token. For example −
Live Demo
#include <stdio.h>
int main(void) {
int token34 = 40;
tokenpaster(34);
return 0;
}
When the above code is compiled and executed, it produces the following result −
token34 = 40
It happened so because this example results in the following actual output from the
preprocessor −
This example shows the concatenation of token##n into token34 and here we have used
both stringize and token-pasting.
Live Demo
#include <stdio.h>
int main(void) {
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
When the above code is compiled and executed, it produces the following result −
One of the powerful functions of the CPP is the ability to simulate functions using
parameterized macros. For example, we might have some code to square a number as follows
−
int square(int x) {
return x * x;
}
Macros with arguments must be defined using the #define directive before they can be used.
The argument list is enclosed in parentheses and must immediately follow the macro name.
Spaces are not allowed between the macro name and open parenthesis. For example −
Live Demo
#include <stdio.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void) {
printf("Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}
When the above code is compiled and executed, it produces the following result −
Conditional Compilation
In C programming language, several directives control the selective compilation of portions
of the program code. They are as follows −
#if
#else
#elif
#endif
The general form of #if is as follows −
#if constant_expression
statement sequence
#endif
Amongst other things, #if provides an alternative method of "commenting out" code.
For example,
#if 0
printf("#d", total);
#endif
#undef
#line
#line changes the contents of __LINE__ which contains the line number of the currently
compiled code and __FILE__ which is a string that contains the name of the source file being
compiled. Both of which are predefined identifiers in the compiler.
#pragma
Example
Following is the C program to demonstrate #ifdef, #ifndef , #else and #endif −
Live Demo
# include <stdio.h>
# define a 10
void main(){
#ifdef a
printf("
Hello I am here..");
#endif
#ifndef a
printf("
Not defined ");
#else
printf("
R u There ");
#endif
Output
When the above program is executed, it produces the following result −
Hello I am here..
R u There
Parameter Passing in C
When a function gets executed in the program, the execution control is transferred from
calling-function to called function and executes function definition, and finally comes back to
the calling function. When the execution control is transferred from calling-function to called-
function it may carry one or number of data values. These data values are called as parameters.
Actual Parameters
Formal Parameters
The actual parameters are the parameters that are speficified in calling function. The formal
parameters are the parameters that are declared at called function. When a function gets
executed, the copy of actual parameter values are copied into formal parameters.
In C Programming Language, there are two methods to pass parameters from calling function
to called function and they are as follows...
Call by Value
Call by Reference
In call by value parameter passing method, the copy of actual parameter values are
copied to formal parameters and these formal parameters are used in called
function. The changes made on the formal parameters does not effect the values
of actual parameters. That means, after the execution control comes back to the
calling function, the actual parameter values remains same. For example consider the
following program...
Example Program
#include<stdio.h>
#include<conio.h>
void main(){
clrscr() ;
num1 = 10 ;
num2 = 20 ;
int temp ;
temp = a ;
a=b;
b = temp ;
Output:
In the above example program, the variables num1 and num2 are called actual parameters and
the variables a and b are called formal parameters. The value of num1 is copied into a and the
value of num2 is copied into b. The changes made on variables a and b does not effect the
values of num1 and num2.
Call by Reference
In Call by Reference parameter passing method, the memory location address of the actual
parameters is copied to formal parameters. This address is used to access the memory locations
of the actual parameters in called function. In this method of parameter passing, the formal
parameters must be pointer variables.
That means in call by reference parameter passing method, the address of the actual parameters
is passed to the called function and is recieved by the formal parameters (pointers). Whenever
we use these formal parameters in called function, they directly access the memory locations
of actual parameters. So the changes made on the formal parameters effects the values of
actual parameters. For example consider the following program...
Example Program
#include<stdio.h>
#include<conio.h>
void main(){
clrscr() ;
num1 = 10 ;
num2 = 20 ;
getch() ;
}
void swap(int *a, int *b) // called function
int temp ;
temp = *a ;
*a = *b ;
*b = temp ;
Output:
In the above example program, the addresses of variables num1 and num2 are copied to
pointer variables a and b. The changes made on the pointer variables a and b in called function
effects the values of actual parameters num1 and num2 in calling function.