You are on page 1of 18

Address in C

Before you get into the concept of pointers, let's first get familiar with address in C.

If you have a variable var in your program, &var will give you its address in the
memory, where & is commonly called the reference operator.

You must have seen this notation while using scanf() function. It was used in the
function to store the user inputted value in the address of var.

scanf("%d", &var);

Pointer variables
In C, you can create a special variable that stores the address (rather than the
value). This variable is called pointer variable or simply a pointer.

How to create a pointer variable?

data_type* pointer_variable_name;

int* p; or int *p

Above statement defines, p as pointer variable of type int.

Reference operator (&) and Dereference operator (*)


As discussed, & is called reference operator. It gives you the address of a variable.

Likewise, there is another operator that gets you the value from the address, it is
called a dereference operator  *.
Int* pc;

Int c = 22;

pc = &c;

*pc = 2;

Common mistakes when working with pointers


Suppose, you want pointer pc to point to the address of c. Then,

int c, *pc;

// Wrong! pc is address whereas,


// c is not an address.
pc = c;
// Wrong! *pc is the value pointed by address whereas,
// &c is an address.
*pc = &c;

// Correct! pc is an address and,


// &c is also an address.
pc = &c;

// Correct! *pc is the value pointed by address and,


// c is also a value (not address).
*pc = c;

C - Pointer arithmetic

There are four arithmetic operators that can be used on pointers: ++, --,
+, and -

To understand pointer arithmetic, let us consider that ptr is an integer


pointer which points to the address 1000. Assuming 32-bit integers, let
us perform the following arithmetic operation on the pointer −
ptr++

After the above operation, the ptr will point to the location 1004 because
each time ptr is incremented, it will point to the next integer location
which is 4 bytes next to the current location

Pointer Comparisons
Pointers may be compared by using relational operators, such as ==, <,
and >. If p1 and p2 point to variables that are related to each other,
such as elements of the same array, then p1 and p2 can be meaningfully
compared.
C Pointers and Arrays

Now, check this simple program. This program prints address of each individual
element of an array.

#include <stdio.h>
int main()
{
int x[4];
int i;

for(i = 0; i < 4; ++i)


{
printf("&x[%d] = %u\n", i, &x[i]);
}

printf("Address of array x: %u", x);

return 0;
}

When you run the program, the output will be something like:

&x[0] = 1450734448

&x[1] = 1450734452

&x[2] = 1450734456

&x[3] = 1450734460
Address of array x: 1450734448

There is a difference of 4 bytes between two consecutive elements of array x. It is


because the size of int is 4 bytes (on our compiler).

Notice that, printing &x[0] and x gave us the same result.

Relation between Arrays and Pointers


Consider an array:

int x[4];

145073

145073

From the above example, it's clear that x and &x[0] both contains the same address.
Hence, &x[0] is equivalent to x.

And, x[0] is equivalent to *x.

Similarly,

 &x[1] is equivalent to x+1 and x[1] is equivalent to *(x+1).


o Here adding 1 to X means add 4 bytes to x that gives next element
address
 &x[2] is equivalent to x+2 and x[2] is equivalent to *(x+2).
 ...
 Basically, &x[i] is equivalent to x+i and x[i] is equivalent to *(x+i).

Array names are converted to pointers, that is they point to begin element, x and &x[0] both
contains the same address
There are few cases where array name doesn't decay into a pointer. To learn more,
visit: When does array name doesn't decay into a pointer?

1. when it's the argument of the & (address-of) operator.


2. when it's the argument of the sizeof operator.
3. When it's a string literal of type char [N + 1] or a wide string literal of type wchar_t [N
+ 1](N is the length of the string) which is used to initialize an array, as in char str[] =
"foo"; or wchar_t wstr[] = L"foo";

Example 2: Arrays and Pointers


#include <stdio.h>
int main()
{
int x[5] = {1, 2, 3, 4, 5};
int* ptr;

ptr = &x[2];

printf("*ptr = %d \n", *ptr);


printf("*ptr+1 = %d \n", *ptr+1);
printf("*ptr-1 = %d", *ptr-1);

return 0;
}

When you run the program, the output will be:

*ptr = 3

*ptr+1 = 4

*ptr-1 = 2
C Call by Reference: Using pointers

Example: Passing address to a Function

#include <stdio.h>
void swap(int *n1, int *n2);

int main()
{
int num1 = 5, num2 = 10;

// address of num1 and num2 is passed


swap( &num1, &num2);

printf("num1 = %d\n", num1);


printf("num2 = %d", num2);
return 0;
}

// pointer n1 and n2 stores the address of num1 and num2 respectively


void swap(int* n1, int* n2)
{
int temp;
temp = *n1;
*n1 = *n2;
*n2 = temp;
}
Return pointer from functions in C

We have seen in the last chapter how C programming allows to return an


array from a function. Similarly, C also allows to return a pointer from a
function. To do so, you would have to declare a function returning a
pointer as in the following example −

int * myFunction() {

Second point to remember is that, it is not a good idea to return the


address of a local variable outside the function, so you would have to
define the local variable as static variable

#include <stdio.h>

#include <time.h>

/* function to generate and return random numbers. */

int * getRandom( ) {

static int r[10];

int i;

/* set the seed */

srand( (unsigned)time( NULL ) );

for ( i = 0; i < 10; ++i) {

r[i] = rand();
printf("%d\n", r[i] );

return r;

/* main function to call above defined function */

int main () {

/* a pointer to an int */

int *p;

int i;

p = getRandom();

for ( i = 0; i < 10; i++ ) {

printf("*(p + [%d]) : %d\n", i, *(p + i) );

return 0;

C - Pointer to Pointer

When we define a pointer to a pointer, the first pointer contains the address
of the second pointer, which points to the location that contains the actual
value as shown below.
A variable that is a pointer to a pointer must be declared as such. This is
done by placing an additional asterisk in front of its name. For example,
the following declaration declares a pointer to a pointer of type int −
int **var;

When a target value is indirectly pointed to by a pointer to a pointer,


accessing that value requires that the asterisk operator be applied twice,
as is shown below in the example −

#include <stdio.h>

int main () {

int var;

int *ptr;

int **pptr;

var = 3000;

/* take the address of var */

ptr = &var;

/* take the address of ptr using address of operator & */

pptr = &ptr;

/* take the value using pptr */

printf("Value of var = %d\n", var );

printf("Value available at *ptr = %d\n", *ptr );


printf("Value available at **pptr = %d\n", **pptr);

return 0;

C Dynamic Memory Allocation

Sometimes, the size of array you declared may be insufficient. To solve this issue,
you can allocate memory manually during run-time. This is known as dynamic
memory allocation in C programming.

There are 4 library functions defined under <stdlib.h> makes dynamic memory


allocation in C programming. They are malloc(), calloc(), realloc() and free().

C malloc()
The name "malloc" stands for memory allocation.

The malloc() function reserves a block of memory of the specified number of bytes.


And, it returns a pointer of type void which can be casted into pointer of any form.

Syntax of malloc()
ptr = (cast-type*) malloc(byte-size)

Example:

ptr = (int*) malloc(100 * sizeof(int));


Considering the size of int is 4 bytes, this statement allocates 400 bytes of memory.
And, the pointer ptr holds the address of the first byte in the allocated memory.

Syntax of calloc()
ptr = (cast-type*)calloc(n, element-size);

Example:

ptr = (float*) calloc(25, sizeof(float));

This statement allocates contiguous space in memory for 25 elements each with the
size of float

C free()
Dynamically allocated memory created with either calloc() or malloc() doesn't get
freed on their own. You must explicitly use free() to release the space.

Syntax of free()
free(ptr);

This statement frees the space allocated in the memory pointed by ptr.

Example 1: malloc() and free()


This program calculates the sum of n numbers entered by the user. To perform this
task, memory is dynamically allocated using malloc(), and memory is freed
using free() function.

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

int main()
{
int n, i, *ptr, sum = 0;

printf("Enter number of elements: ");


scanf("%d", &n);

ptr = (int*) malloc(n * sizeof(int));


if(ptr == NULL)
{
printf("Error! memory not allocated.");
exit(0);
}

printf("Enter elements: ");


for(i = 0; i < n; ++i)
{
scanf("%d", ptr + i);
sum += *(ptr + i);
}

printf("Sum = %d", sum);


free(ptr);
return 0;
}

C realloc()
If the dynamically allocated memory is insufficient or more than required, you can
change the size of previously allocated memory using realloc() function

Syntax of realloc()
ptr = realloc(ptr, x);
Here, ptr is reallocated with new size x.

QUESTIONS

36. What will be the output of the C program?


#include<stdio.h>
int main(){
int i = 5;
void *vptr;
vptr = &i;
printf("\nValue of iptr = %d ", *vptr);
return 0;
}

37. Fill the question mark to get "void pointer" as an output?


#include<stdio.h>
int main(){
char *ptr = "void pointer";
void *vptr;
vptr = &ptr;
printf("%s" , ?);
return 0;
}

38. What will be the output of the C program?


#include<stdio.h>
#define NULL "error";
int main()
{
char *ptr = NULL;
printf("%s",ptr);
return 0;
}

40. Fill the question mark to get "5" as an output?


#include<stdio.h>
int main()
{
int i = 5,*ptr;
ptr= &i;
void *vptr;
vptr = &ptr;
printf("\nValue of iptr = %d ", ?);
return 0;
}

What is indirection?
If you declare a variable, its name is a direct reference to its value. If you have a pointer to a
variable, or any other object in memory, you have an indirect reference to its value. If p is a
pointer, the value of p is the address of the object. *p means "apply the indirection operator to p";
its value is the value of the object that ppoints to. (Some people would read it as "Go indirect
on p.")
What is a null pointer?
There are times when it's necessary to have a pointer that doesn't point to anything. The
macro NULL, defined in <stddef.h>, has a value that's guaranteed to be different from any valid
pointer. NULL is a literal zero

What is a void pointer?
A void pointer is a C convention for "a raw address." The compiler has no idea what type of
object a voidpointer "really points to." If you write
int *ip;
ip points to an int. If you write
void *p;
p doesn't point to a void!
In C and C++, any time you need a void pointer, you can use another pointer type. For example,
if you have a char*, you can pass it to a function that expects a void*. You don't even need to
cast it. In C (but not in C++), you can use a void* any time you need any kind of pointer, without
casting. (In C++, you need to cast it.)
When is a void pointer used?
A void pointer is used for working with raw memory or for passing a pointer to an unspecified
type.

Can you subtract pointers from each other? Why would you?
If you have two pointers into the same array, you can subtract them. The answer is the number
of elements between the two elements.

Is NULL always equal to 0(zero)?


The answer depends on what you mean by "equal to." If you mean "compares equal to," such as

if ( /* ... */ )
{
p = NULL;
}
else
{
p = /* something else */;
}
/* ... */
if ( p == 0 )

then yes, NULL is always equal to 0. That's the whole point of the definition of a null pointer.
If you mean "is stored the same way as an integer zero," the answer is no, not necessarily.
That's the most common way to store a null pointer. On some machines, a different
representation is used
What does it mean when a pointer is used in an if statement?
Any time a pointer is used as a condition, it means "Is this a non-null pointer?" A pointer can be
used in an if, while, for, or do/while statement, or in a conditional expression
Can you add pointers together? Why would you?
No, you can't add pointers together. 

How do you use a pointer to a function?


. You want to create a pointer, pf, that points to the strcmp() function. The strcmp() function
is declared in this way:

int strcmp( const char *, const char * )

To set up pf to point to the strcmp() function, you want a declaration that looks just like
the strcmp()function's declaration, but that has *pf rather than strcmp:

int (*pf)( const char *, const char * );


Assign address of stcmp
Pf = strcmp;

Call the function


pf( str1, str2 ) > 0

When would you use a pointer to a function?


Pointers to functions are interesting when you pass them to other functions. A function that takes
function pointers says, in effect, "Part of what I do can be customized. Give me a pointer to a
function, and I'll call it when that part of the job needs to be done

Can the size of an array be declared at runtime?


No. In an array declaration, the size must be known at compile time. You can't specify a size
that's known only at runtime

19. What is the stack?


Stack is used for static memory allocation. Both stack and heap stored in RAM

Variables allocated on the stack are stored directly to the memory and access to this memory is very fast, and
it's allocation is dealt with when the program is compiled.

There used to be a C function that any programmer could use for allocating memory off the
stack. The memory was automatically deallocated when the calling function returned. This was a
dangerous function to call; it's not available anymore.
20. What is the heap?
Heap is used for dynamic memory allocation.The heap is where malloc(), calloc(),
and realloc() get memory.
Getting memory from the heap is much slower than getting it from the stack. On the other hand,
the heap is much more flexible than the stack. Memory can be allocated at any time and
deallocated in any order. Such memory isn't deallocated automatically; you have to call free().

Variables allocated on the heap have their memory allocated at run


time and accessing this memory is a bit slower, but the heap size is
only limited by the size of virtual memory 

What is the difference between NULL and NUL?


NULL is a macro defined in <stddef.h> for the null pointer.
NUL is the name of the first character in the ASCII character set. It corresponds to a zero value.

Can math operations be performed on a void pointer?


No. Pointer addition and subtraction are based on advancing the pointer by a number of
elements. By definition, if you have a void pointer, you don't know what it's pointing to, so you
don't know the size of what it's pointing to.

You might also like