How to Use Pointers in C Programming

Valentine Gatwiri

If you are learning C programming, you have probably heard the term "pointer" before.

Pointers are one of the most important and powerful features of the C programming language. They allow us to manipulate memory directly, which can be very useful in many programming scenarios.

In C, a pointer is simply a variable that holds a memory address. We can think of it as a way to refer to a specific location in memory.

How to Declare a Pointer

To declare a pointer variable in C, we use the asterisk * symbol before the variable name. There are two ways to declare pointer variables in C:

Both of these declarations are equivalent and they declare a pointer variable named "p" that can hold the memory address of an integer.

However, it's important to note that if you declare multiple variables in a single statement, you need to include the asterisk before each variable name to indicate that they are all pointers. For example:

This declares three pointer variables named "p", "q", and "r" that can hold the memory address of an integer.

How to Initialize a Pointer

When we declare a pointer variable, it does not automatically point to any particular memory location. To initialize a pointer to point to a specific variable or memory location, we use the ampersand & operator to get the address of that variable.

For example, to initialize the pointer p to point to an integer variable called x , we would write:

This sets the value of p to be the memory address of x .

How to Dereference a Pointer

Once we have a pointer that points to a specific memory location, we can access or modify the value stored at that location by dereferencing the pointer.

To dereference a pointer, we use the asterisk * symbol again, but this time in front of the pointer variable itself. For example, to print the value of the integer that p points to, we would write:

What Does "Pointer to a Pointer" Mean?

A pointer can also point to another pointer variable. This is known as a "pointer to a pointer". We declare a pointer to a pointer by using two asterisks ** . For example:

Here, q is a pointer to a pointer. It points to the address of the p variable, which in turn points to the address of the x variable

How to Pass Pointers to Functions

We can pass pointers to functions as arguments, which allows the function to modify the value of the original variable passed in. This is known as "passing by reference".

To pass a pointer to a function, we simply declare the function parameter as a pointer. For example:

Here, the increment function takes a pointer to an integer ( int *p ) and increments the value of the integer by one ( (*p)++ ).

In main() , we declare the integer x and a pointer p that points to x . We then call the increment function, passing in the p pointer. After the function call, x has been incremented to 43 .

How to Use Pointers for Dynamic Memory Allocation

One of the most powerful uses of pointers in C is for dynamic memory allocation. This allows us to allocate memory at runtime, rather than at compile time.

We use the malloc function to dynamically allocate memory, and it returns a pointer to the allocated memory. For example:

Here, p is a pointer to an integer that has been allocated using malloc . The sizeof operator is used to determine the size of an integer in bytes.

After allocating memory, we can use the pointer variable like any other pointer. When we are finished with the memory, we should free it using the free function. For example:

This frees up the memory that was allocated to p .

What is Pointer Casting?

Sometimes you may need to cast a pointer from one type to another. You can do this using the (type *) syntax. For example:

Here, p is cast to a pointer to a double type.

How Does Pointer Arithmetic Work?

Because pointers hold memory addresses, we can perform arithmetic operations on them to move them to different memory locations.

For example, we can increment a pointer to move it to the next memory location. This is often used in array operations, where we use a pointer to access elements of an array.

For example, to print the first element of an integer array using a pointer, we could write:

Here, p is set to point to the first element of the arr array, and *p dereferences the pointer to get the value of the first element (which is 1 ).

How to Use Pointer Arrays

We can also declare arrays of pointers in C. For example:

This declares an array of three pointers to integers. Each element of the array can point to a separate integer variable.

Pointer Arithmetic and Arrays

We can use pointer arithmetic to access elements of an array. For example:

Here, p is set to point to the first element of the arr array. We can use pointer arithmetic to access the second element of the array ( *(p + 1) ), which is 2 .

Example of How to Use Pointers

Here's an example program that demonstrates some of the concepts we've discussed:

Screenshot-from-2023-05-01-12-03-41

This program demonstrates several concepts related to pointers.

First, we declared an integer variable x and a pointer p that points to x . We called the increment function, passing in the p pointer. The increment function modifies the value of x by incrementing it by one. We then printed the value of x before and after the function call to demonstrate that x has been incremented.

Next, we used dynamic memory allocation to allocate an array of three integers. We set the values of the array elements using pointer arithmetic ( arr[0] = 1 , arr[1] = 2 , etc.). We then declared a pointer q that points to the first element of the array. Furthermore, we used pointer arithmetic to access and print the values of each element of the array.

Finally, we freed the memory that was allocated to the array using the free function.

This program demonstrates how pointers can be used to modify the value of a variable, access elements of an array using pointer arithmetic, and dynamically allocate and free memory.

Common Pointer Errors

Pointers can be tricky to work with, and they can lead to some common errors.

One common error is using an uninitialized pointer. If you declare a pointer variable but do not initialize it to point to a valid memory location, you may get a segmentation fault or other error when you try to dereference the pointer.

Another common error is dereferencing a null pointer, which can also cause a segmentation fault.

Another error to be aware of is using the wrong type of pointer. For example, if you declare a pointer to an integer but then try to dereference it as a pointer to a character, you may get unexpected results or errors.

Pointers are a powerful tool in C programming, but they can be a bit tricky to work with. With practice and patience, you can master pointers and use them to manipulate memory and work with complex data structures.

Thank you for reading!

A curious full-stack web developer. I love solving problems using software development and representing Data in a meaningful way. I like pushing myself and taking up new challenges.

If you read this far, thank the author to show them you care. Say Thanks

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

C Functions

C structures, creating pointers.

You learned from the previous chapter, that we can get the memory address of a variable with the reference operator & :

In the example above, &myAge is also known as a pointer .

A pointer is a variable that stores the memory address of another variable as its value.

A pointer variable points to a data type (like int ) of the same type, and is created with the * operator.

The address of the variable you are working with is assigned to the pointer:

Example explained

Create a pointer variable with the name ptr , that points to an int variable ( myAge ). Note that the type of the pointer has to match the type of the variable you're working with ( int in our example).

Use the & operator to store the memory address of the myAge variable, and assign it to the pointer.

Now, ptr holds the value of myAge 's memory address.

Dereference

In the example above, we used the pointer variable to get the memory address of a variable (used together with the & reference operator).

You can also get the value of the variable the pointer points to, by using the * operator (the dereference operator):

Note that the * sign can be confusing here, as it does two different things in our code:

  • When used in declaration ( int* ptr ), it creates a pointer variable .
  • When not used in declaration, it act as a dereference operator .

Good To Know: There are two ways to declare pointer variables in C:

Notes on Pointers

Pointers are one of the things that make C stand out from other programming languages, like Python and Java .

They are important in C, because they allow us to manipulate the data in the computer's memory. This can reduce the code and improve the performance. If you are familiar with data structures like lists, trees and graphs, you should know that pointers are especially useful for implementing those. And sometimes you even have to use pointers, for example when working with files and memory management .

But be careful ; pointers must be handled with care, since it is possible to damage data stored in other memory addresses.

C Exercises

Test yourself with exercises.

Create a pointer variable called ptr , that points to the int variable myAge:

Start the Exercise

Get Certified

COLOR PICKER

colorpicker

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail: [email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail: [email protected]

Top Tutorials

Top references, top examples, get certified.

DEV Community

DEV Community

Aniket Bhattacharyea

Posted on Sep 9, 2021

(Almost) Everything You Need To Know About Pointers in C

When I was first starting out with C, pointers were something that confused me the most. I was scared of pointers and could never understand how to use them.

No, I didn't say that! In fact, pointers have always been intuitive to me. But most of the students starting to learn C are put off by the idea of pointers. It is one of those areas of C which are not explained properly to students. resulting in many misconceptions about them.

In this huge post, I have compiled almost everything that is fundamental to pointers. Of course, it is a huge topic, and it's not possible to cover the entirety of it in one post, but once you know these fundamentals, you'll be able to use them more efficiently, and hopefully will be able to tackle pointers in a program.

Let's start.

Beginning With Pointer Sorcery

One fine afternoon, you are lying on your couch and thinking about the year 2038 problem and the end of the universe, and suddenly your friend calls you and asks "Hey, I want to come over and contemplate our existence, but I do not know where your house is!"

You say, "No problem buddy. I'll give you a copy of my home."

Of course, you'd never say that. Instead, you will give him your address so that he can come over. Now, you could make him a copy of your home if you're generous enough, but it takes time and defeats the purpose of your friend coming over. He wants to come to your house, not a copy.

Now think in terms of programming. At the time when C was created, memory was scarce, and being efficient was not only needed but vital. For this reason, you'd have to be really careful while dealing with memory. You'd really not like to make unnecessary copies of something.

Another case you can consider is of having "side effect" of a function. Consider this simple program.

which just prints

Even though you are calling the function f with the variable a as a parameter, and f is changing the value of a . the change doesn't show up in the original value of a , because when you are calling the function f , you are passing a copy of a , not a itself. In other terms, you are giving your friend a copy of your house.

This is desired in most cases. You don't really want your functions to accidentally change any variable where it's not supposed to. But sometimes, you actually want the function to change a variable. You have already seen such a function that can change the actual parameter.

How does scanf change the value of n ? The answer is through pointers.

Also, take a look at this classic example of swap-

It works, except it doesn't.

swap does swap the variables, but since you are making a copy of a , and b , the change doesn't show up outside the function. But we want the function to be able to change the actual variables. So we need to have some kind of way to pass the actual a and b . But in C, there is no way you can pass "actual" variables. (which is not the case in C++).

One way you might end up doing is to make a and b global

And it now works, because swap now can access a and b , but having global variables is a real bad idea .

The way? Give swap the addresses of a and b . If it has addresses of a and b , it can change them directly.

Pointers are nothing but variables that hold the address of another variable.

Now, where does this address come from? We know how bits and bytes work . The RAM of the computer can be thought of as a mess, a really long one, with lots of rooms one after another, and each byte is a room. How does the computer know which room to put data in? It gives a number to each room, and that number is the address.

When I write

I tell the compiler "Buddy, reserve one room in the mess, and call it a " . Why one room? Because the size of char is 1 byte. (Note that C's definition of a byte is basically the sizeof char , which in some rare cases might not be actually 1 byte in the machine, however, it is always 1 byte in C)

I tell the compiler to reserve the number of rooms necessary for int and call it b .

Side rant: People coming from Turbo C, and being told size of int is 2 bytes, it's not necessarily so, and probably not so in any modern computer. The C standard guarantees at least 2 bytes for int and on my machine sizeof(int) is 4, so we will stick to that for the rest of this post.

Now that our b has 4 rooms, it will stay in the rooms starting from the first one. So that when we say "address of b", we actually mean "address of the starting or ending byte of b". (See big endian and little endian . For this tutorial, let's assume it's the ending byte because it is so on my machine)

In order to get the address of b and store it, we need to use a pointer variable. Just like any other variable, a pointer also has a type, defined by the type of the thing it points to. The syntax is type_of_the_thing_it_points_to *name

Note that the asterisk need not be adjoined to the variable name. Any of these is valid -

We will prefer the 2nd syntax. We will see in a short while why.

Let's first see how to assign a value to a pointer. In order to make a pointer point to a variable, we have to store the address of the variable in the pointer. The syntax for getting the address of a variable is &variable_name .

If you run this program, you will see something like 0x7ffc2fc4ff27 . That is the value of the pointer, which is the address of the variable a (this is in hexadecimal). This value is not fixed. If you run the program again, the value will likely change, because a will be stored somewhere else.

One thing you might have noticed. Although we are declaring it as *pa , the * is not used when printing the pointer. In fact, * is not a part of the name of the pointer. The name of the pointer is just pa . The * is instead used to get the value of whatever thing the pointer is pointing to (known as dereferencing).

So, quickly revise -

  • pa is the value of the pointer, which is the address of a .
  • *pa is the value of the thing pa is pointing to, in this case a .

One more time.

  • pointer_name is the value of the pointer itself.
  • *pointer_name is the value of the thing the pointer points to.

Now, this should be clear.

Now we can rewrite the swap function as follows -

And call it with the addresses swap(&a, &b) . This works and the change shows up outside the function too. Because once you have the address of a variable, you know where it lives in memory so you can freely change it.

You might have a valid question. Since all pointers are just addresses, which are basically numbers, why is the type of the thing it points to necessary? Why do we distinguish between char* and int* although both of them are just some numbers?

The answer is clear. When you dereference a pointer, the compiler needs to know what data type is the object. Remember that address of a variable is just the address of the ending byte of the variable. In order to read the variable, the compiler needs to know its type so that it knows how many bytes to read.

Consider this program

It prints (ignore the compiler warning)

What happened here?

If you represent 1101214537 in binary it is 01000001 10100011 00110011 01001001 . So &a which is the address of a points to the byte in memory that contains the last byte of the number, which is 01001001 . When I dereference pa , the compiler sees that it points to char so it reads only one byte at that address, giving the value 01001001 which 73 , the ASCII for I . This is why the type is absolutely and you should not mix and match types unless you are absolutely sure of what you are doing. (We'll see a few examples)

Remember we told that we will prefer int *pa rather than int* pa although they are the same? The reason is to safeguard against the following common misconception. Can you find the difference?

If you are a beginner, you will assume that since int a, b makes both a and b as int , then int* pa, pb will make both pa and pb as int* . But it doesn't. The reason is * "binds" to the variable name, not the type name. If instead, you'd have written

you'd rightly conclude pa is a pointer to int, and pb is just int . Hence I prefer to write the * with the variable name, however, there are compelling reasons for the other style as well, and if you are careful enough, you can use the other style as well.

NULL and void pointer

These two are a special types of pointers in C. The Null pointer is used to denote that the pointer doesn't point to a valid memory location.

We use Null pointer in various ways, for example, to denote failure, or mark the end of a list of unknown size, etc. Dereferencing a Null pointer is undefined behavior and your program will likely crash.

Note that the Null pointer is not the same as pointer to memory address 0, although it's very likely to be so. There are exceptions, for example in small embedded devices where address 0 might be a valid location.

Void pointer is one more interesting pointer in C. Basically void pointer "throws away" the type of a pointer. It is a general-purpose pointer that can hold any type of pointer and can be cast to any type of pointer. The following are all valid -

But you can't dereference a void * because it doesn't have a type. Trying to dereference a void * will give you an error. However, you can cast it to anything you want and then dereference it, although it's not a very good idea and it violates the type aliasing rules.

Here we're removing the type of &a through p and casting it to a char * . Essentially a is getting read as a char and this prints A .

Be careful during casting. You should use void pointers only if you are absolutely sure of what you're doing.

Sometimes you'll see char * used as a generic pointer as well. This is because void * was not present in old versions of C, and some practice remains, or maybe the code needs to do pointer arithmetic on that pointer.

Generally void * i s used in places where you expect to work with pointers to multiple types. As an example, consider the famous memcpy function which copies a block of memory. Here is the signature of memcpy -

As you see, it accepts void * , which means it works with any type of pointers. As for an example (copied from cplusplus ) -

In line 15, we invoked memcpy with char * and in line 19, we invoked memcpy with a pointer to structure, and they both work.

Pointer arithmetic

Since pointers are just like other variables, you'd expect that we should be able to do arithmetic with them. We can, but there's a catch. First of all, we are only allowed these 2 operations -

  • Addition (and hence subtraction) of an integer constant to a pointer.
  • Subtraction of two pointers of the same type.

Let's see them one by one

This prints

Strangely, it seems pa+1 increments the pointer by 4, and not by 1. The reason lies in the datatype of the thing it points to, in this case, int . Remember that a pointer must always point to something. When you increment the pointer by 1, it points to the next thing.

In this case, pa points to an int . Where is the next int ? After 4 bytes of course, because the size of int is 4 bytes.

Similarly pa-1 points to the previous int which lies 4 bytes before.

By the same logic, pa+2 points to the int 2 places after a that is 4 * 2 = 8 bytes after a , and pa+n points to the integer n places after a which is 4n bytes after a .

An observant reader might have noticed that things are looking almost like an array, and he/she is not wrong completely. In a few minutes, we shall explore the idea of array using pointers. Before let's talk about the subtraction of pointers.

Similar to the previous case, although the difference between pa and pb is of 8 bytes as numbers, as pointers the difference is 2. The negative sign of pa-pb implies that pb points after pa .

To quickly summarise -

  • If I have some_data_type *p , then pa + n increments the pointer by n * sizeof(some_data_type) bytes.
  • If I have some_data_type *p, *q then p - q is equal to the difference in bytes divided by sizeof(some_data_type)

Let's consider what happens if we mix indirection and prefix or postfix increment/decrement operators. Can you guess what each of these does? I have omitted the data types so that you can't guess ;-). Assume p points to int

In order to answer, you have to remember the precedence -

  • Postfix ++ and -- have higher precedence than *
  • Prefix ++ and -- have the same precedence as * .

Since the * operator is itself a prefix, you'll never have a problem with prefix increment or decrement. You can tell just by the order of the operator. For the postfix operator, remember that postfix works first, then indirection.

So *p++ is same as *(p++) . So, the value of p will be used in the expression, then p will be incremented. So x gets the value of *p and p becomes p+1 , so that the type of x ought to be int too.

++*p will probably not arise confusion. This is the same as ++ (*p) . So, first p is dereferenced, and then ++ is applied. So whatever p was pointing to gets incremented by 1 and then it is assigned to x , and p is unchanged. So the type of x is again int .

And finally * ++p is same as * (++p) . So, first p gets incremented by 1, and then it is dereferenced. So x gets the value of whatever is this incremented pointer pointing to.

We can also compare pointers using relational operators like == , <= etc. but there's a catch. You can only compare two pointers using <=, <, >=, > if they both are pointers of the same type, and of the same array or same aggregate object. Otherwise, it is undefined behavior.

Quoting C11 -

When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P . * In all other cases, the behavior is undefined. *

Take a look -

This prints Bye . Well first of all this comparison is valid since p and q are both pointers to int and also they both point to elements of the same struct . Since q was declared later in some_struct , q compares greater to p

For equality, the restriction is a bit slack. You can compare any two pointers as long as they have the same type, or one of them is a null pointer or void pointer. And they compare equal if they point to the same object, or if both are null (doesn't matter if types don't match), or if both are pointing to members of the same union.

Let's demonstrate the last point.

This prints Equal although p and q point to different things, they are within the same union.

Since pointers are just numbers, can you put any integer in them? The answer is yes, but be careful of what you put. In fact, be careful when you dereference it. If you try to dereference an invalid address, your program will likely segfault and crash.

This instantly segfaults.

Admitted to Hogwarts School Of Pointer Magic

Pointers and arrays.

Let's now move to some advanced sorcery - array and pointers.

We know that an array stores its elements contiguously in memory. Which means the elements are stored in order one after another. So if we have int arr[10] , we know arr[1] lies right after arr[0] , arr[2] lies right after arr[1] and so on. So if I have a pointer to arr[0] and I increment it by 1, it should point to arr[1] . If I increment it by 1 again, it should point to arr[2] .

In fact, there are so many similarities between arrays and pointers, that we can talk about the equivalence of arrays and pointers.

Word of caution! This does not mean arrays and pointers are the same and you can use one in place of another. This misconception is quite common and ends up being harmful. Arrays and pointers are very different things, but pointer arithmetic and array indexing are equivalent.

For starters, the name of an array "decays" into a pointer to the first element. What do I mean by that? Consider this code -

But aren't we mixing up datatypes in the case of pb ? pb is a pointer to int and arr is an array of int!

Turns out that arr is converted to a pointer to the first element. So that arr and &(arr[0]) is equivalent.

Quick note: indexing operator [] has higher precendence than * so that * arr[0] is same as * (arr[0])

Let's do even more funny stuff -

The first printf is ok. arr[1] means the 2nd element of arr .

We just reasoned about the 2nd line. pa points to the first element of arr . So pa+1 will point to the next int in memory, which is arr[1] because array elements are stored contiguously.

But in the 3rd and 4th lines, aren't we mixing up array and pointer syntax? Well, turns out that arr[i] is just the same as *(arr + i) and this is (almost) what happens internally when you write arr[i] .

Similarly *(pa + i) is the same as pa[i] . Pointer arithmetic works both on arrays and pointers. Similarly, array indexing works on both pointers and arrays.

And for the last part, arr[1] is the same as *(arr + 1) which is the same as *(1 + arr) which should be the same as 1[arr] . This is one of those weird quirks of C.

Does this mean you can mix and match pointers and arrays? The answer is a big fat no. The reason is although arr[i] and pa[i] give you the same result, i. e. the 2nd element of arr , the way they reach there is quite different.

Consider the code

Let's look at the assembly code generated by the compiler. I used Compiler Explorer . Don't worry if you can't read assembly. We'll go together.

We are interested in lines 5 and 6. Here's the related assembly for int arr[3] = {1, 2, 3} .

In case you are seeing assembly for the first time, rbp is the base pointer register that holds the memory address of the base of the current stack frame. Don't worry about what that means. For now think of rbp as a pointer variable, which points to some location in memory.

Here the contents of arr is being put in memory. For example, consider the first line. The mov instruction puts the value 1 somewhere in memory. The DWORD PTR tells that it is of size 32 bit or 4 bytes as it is an int . The syntax [rbp - 28] means the content of the memory location at the address rbp-28 . Remember that rbp is like a pointer. So it is the same as doing * (rbp - 28) .

Putting everything together, we see that the first line puts the value 1 in the memory address pointed by rbp-28 . The next value should be stored right after it, i. e. after 4 bytes. Which should be pointed by rbp-24 and indeed that is where 2 is stored. And finally, 3 is stored in the memory address pointed by rbp-20 .

So, we see that the address of the first element is rbp-28 . So we'd expect this should be reflected in the line int *pa = arr; . And indeed it is -

lea means load effective address which calculates rbp-28 and stores the address in rax rather than fetching the content of the memory address   rbp-28 and storing the content . In other words, it just copies the address of the first element in rax register and then in the memory location rbp-8 which is our pa .

Now let's look at int a = arr[1]

So here first the content of rbp-24 is loaded into eax and then stored in rbp-12 which is our a . The interesting thing to notice is that the compiler knows the first element of arr is at rbp-28 so when you write arr[1] it directly offsets the base address by and gets rbp-24`. This happens in compile time.

Now let's look at int b = pa[1];

Here we see first the value stored at rbp-8 is moved to rax . Remember this was our pa variable? So first the value stored at pa is read. Then it is offset by 1, so we get rax + 4 and we read the value at rax+4 and store it to eax . Finally, we store the value from eax to rbp-16 which is the b variable.

The noticeable difference is that it takes one extra instruction in case of pointer. Because array address is fixed, when you write arr , the compiler knows what you're talking about. But a pointer value can be changed. So when you write pa , the value of pa needs to be read first and then it can be used.

Now suppose something like this. You have two files. One contains a global array like

And in another file, you get carried away by the equivalence of array and pointer and write

In other words, you have declared arr as a pointer but defined as an array. What will happen if you write int a = arr[1] ?

The answer is - something catastrophic. Let's see why.

Let's assume the array elements are stored just like before -

But in our second file, we are doing arr[1] . So it will do something like

Can you see the problem? We are reading the content at rbp-28 , but the content is 1, the first element of the array. So, essentially we are reading the content of memory address 1+4=5 which is an invalid location!

Bottom line: Don't mix and match.

Another difference is that a pointer name is a variable, but an array name is not. So you can do pa++ and pa=arr but you cannot do arr=pa and arr++

But, there is a case where arrays and pointers are the same. That is in function parameters -

What is the difference between arr and pa ? There is no difference

The compiler treats arr and pa both as pointers, and that's about the only case you can be certain that using pointer in place of array works.

Technically, this is an illustration of an array-like syntax being used to declare pointers, rather than an example of pointers and arrays being the same.

Since pointers are like any other variable, you can have a pointer to pointers too.

Here pa is a pointer to pointer to int . So, *pa will give you a pointer to int , and finally **pa will give you an int

You can have pointers to array too. But before that, remember [] has higher precedence than *

What's the difference between pointer to an array and normal pointer? Consider

So, essentially they all point to the same location. And we already know arr is the same as a pointer to the first element. Now we see that &arr also contains the location of the first element.

Although pa and pb point to the same location, what they point to is very different. pb is a pointer to [int] so it points to a [int] which is the first element of arr whereas pa is a pointer to [array of 3 elements] so it points to an [array of 3 elements] i. e. the whole arr .

This is evident when you try to do arithmetic -

pb is a pointer to int . So pb+1 points to the next int 4 bytes after. Whereas pa is a pointer to array of 3 int . So pa+1 will point to the next array of 3 int which is 3 * 4 = 12 bytes after, and indeed, pa+1 is 12 bytes after pa . ( 0x7fff2632cc90 - 0x7fff2632cc84 = 12, these are in hexadecimal in case you're confused).

You can use a pointer to array just like a normal variable. Just remember the precedence -

The easiest way to remember is "Declaration follows usage." So the usage of a pointer will look like the way it was defined. Since we defined pa as (*pa)[] , its usage will also look the same.

One common mistake that students do, with the fact that arrays decay down to pointers in function parameters is working with multidimensional arrays.

If you have something like

you might think since array names decay to pointers in function parameter, an array of array should decay to a pointer to pointer. So you might write the declaration of f as

Unfortunately, this is wrong and will give a warning (but will compile)

What happened here? It's easy.

If an array of [int] decays down to a pointer to [int], what should an array of [array of int] decay down to? Of course a pointer to [array of int]. Remember that the size is also part of arrays type. So, in our case, arr is an array of [4 element array of int]. So, it decays down to pointer to [4 element array of int].

So you should write

Or, you can just take an array of array

Note that only the size of the rightmost column is required in the formal parameters list.

Pointers and Structures and Unions

Now we move on to struct and union . We can have pointers to them too.

Or if you prefer a typedef

An interesting situation occurs when you want to access members of struct using pointer. Suppose you want to access the member p through pa . You might do

Except, this doesn't do what you expect. The operator . has higher precedence than * so *pa.p is same as *(pa.p) . So instead of dereferencing pa and then accessing the member p , you end up accessing the member p and then dereferencing it. But pa doesn't have a member p . So, it gives a compiler error.

Instead, you want to write this

Which works the way you want. But writing this is tedious, and turns out that we write this so much that they have a special operator ->

pa -> p is same as (*pa).p but looks neat and clean.

The case of unions is a little bit involved. Quoting cppreference -

A pointer to a union can be cast to a pointer to each of its members (if a union has bit field members, the pointer to a union can be cast to the pointer to the bit field's underlying type). Likewise, a pointer to any member of a union can be cast to a pointer to the enclosing union.

What it means is that, if you have a pointer to a union, you can cast it to any of its members, and vice versa. Take a look

Here, I could cast the pointer to a to an int* and it automatically pointed to the member p . Similarly, if I had cast it to char* it would point to q .

Conversely, if I had a pointer to p , I could cast it to a pointer to some_union and it would point to a

This prints a as expected.

Ministry of Pointer Magic

Pointers and function.

It is possible to have pointers to functions too. Remember that the return type, the number of parameters it takes, and the type of each parameter - these 3 are parts of the type of a function. Hence you must provide these during pointer declaration. Also worth noting () has higher precedence than *

A pointer to function can be used just like other pointers -

This prints 2 as you'd expect.

Remember I talked about declaration follows usage? Well, turns out that in the case of pointer to functions, that rule can be ignored. For example, this works

And so does this

And weirdly enough, this too

So, in the case of functions, not only you can dereference as many times as you want, you can drop the dereferencing altogether and just use the pointer as if it were a function itself . Another one of those C quirks.

Finally, you can get wild with pointers and arrays and function like

You get the idea. Yes, it can get pretty messy, but once you know the syntax, and you have cdecl , you can easily breeze through them (or read my article )

As for how you can use a function pointer. here's an example of a simple calculator

We are storing all 4 operations in an array and when the user enters a number, we call the corresponding operation.

Qualified types

Each type in C can be qualified by using qualifiers. In particular we have 3 - const , volatile , and restrict . Here we will look at const and restrict .

Adding const to a type effectively marks it read-only, so that attempting to change the value will result in a compiler error.

Turns out, int const and const int both are valid. Now if I throw pointers into the party, I get some fun stuff

Can you guess which one is what?

To untangle this, we will remember some_data_type *p declares p to be a pointer to some_data_type

Hence, const int *p can be thought of as (const int) *p . So that p is a pointer to a const int . It means, whatever p is pointing to is a const int and you cannot change that. However, p itself is not const and can be changed.

For the second one compare it with int const p which declares p as a read only int . So, int * const p should declare p as read-only int* . This means the pointer itself is const and you can't change p , but you can change what p is pointing to.

And finally, const int * const p declares that both p and *p are read-only. So you can neither change p nor *p .

Now let's look at the restrict keyword. The restrict keyword, when applied to a pointer p , tells the compiler that as long as p is in scope, only p and pointers directly or indirectly derived from it (e. g. p+1 ) will access the thing it's pointing to.

Confused? Let's see an example.

Here is the assembly generated after enabling optimization -

The problem in this function is, p , q and v might point to the same location. So that when you do *p += *v , it might happen that *v also gets changed because p and v were pointing to the same location.

This is why *v is first loaded into eax by mov     eax, DWORD PTR [rdx] . Then it is added to *p . Again, we have to load *v because at this point, we are not sure if *v has changed or not.

Now if I update the function as follows -

the compiler is free to assume that p , q and v all point to different locations, and can load *v only once, and indeed it does

Note that it is up to the programmer to guarantee that the pointers do not overlap. In case they do, it is undefined behavior.

You can read more about restrict here .

That's probably enough for one post. To quickly recap, you have learned -

  • What pointers are.
  • How to declare and dereference pointers.
  • Pointer arithmetic.
  • Pointer comparison.
  • Pointer to array and array of pointers.
  • Pointers and arrays are not the same.
  • Pointer arithmetic and array indexing are equivalent.
  • Array in function parameter decay to a pointer.
  • Pointers to a multidimensional array.
  • Pointers to structures and unions.
  • Pointer to functions.
  • Pointer to wild exotic types.
  • const and restrict with pointers.

Note that most of these hold true in C++ also, although you have minor changes, and some new stuff like smart pointers.

Hopefully, you learned something new in this post. Subscribe to my blog for more.

Top comments (0)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

cezar-plescan profile image

Level Up Your Angular Code: A Transformative User Profile Editor Project (Part 1)

Cezar Pleșcan - Apr 17

rk042 profile image

How To Reverse A Linked List Recursively In Python

rathod ketan - May 5

nfrankel profile image

Implementing the Idempotency-Key specification on Apache APISIX

Nicolas Frankel - Apr 11

mike_andreuzza profile image

How to create a progress-bar with Tailwind CSS and Alpinejs

Michael Andreuzza - Apr 12

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Pointer Basics

Section 1 -- pointer rules, 1) pointers and pointees, 2) dereferencing, 3) pointer assignment, section 2 -- binky's code example, java version, c++ version, pascal version, section 3 -- study questions.

CProgramming Tutorial

  • C Programming Tutorial
  • C - Overview
  • C - Features
  • C - History
  • C - Environment Setup
  • C - Program Structure
  • C - Hello World
  • C - Compilation Process
  • C - Comments
  • C - Keywords
  • C - Identifiers
  • C - User Input
  • C - Basic Syntax
  • C - Data Types
  • C - Variables
  • C - Integer Promotions
  • C - Type Conversion
  • C - Booleans
  • C - Constants
  • C - Literals
  • C - Escape sequences
  • C - Format Specifiers
  • C - Storage Classes
  • C - Operators
  • C - Arithmetic Operators
  • C - Relational Operators
  • C - Logical Operators
  • C - Bitwise Operators
  • C - Assignment Operators
  • C - Unary Operators
  • C - Increment and Decrement Operators
  • C - Ternary Operator
  • C - sizeof Operator
  • C - Operator Precedence
  • C - Misc Operators
  • C - Decision Making
  • C - if statement
  • C - if...else statement
  • C - nested if statements
  • C - switch statement
  • C - nested switch statements
  • C - While loop
  • C - For loop
  • C - Do...while loop
  • C - Nested loop
  • C - Infinite loop
  • C - Break Statement
  • C - Continue Statement
  • C - goto Statement
  • C - Functions
  • C - Main Functions
  • C - Function call by Value
  • C - Function call by reference
  • C - Nested Functions
  • C - Variadic Functions
  • C - User-Defined Functions
  • C - Callback Function
  • C - Return Statement
  • C - Recursion
  • C - Scope Rules
  • C - Static Variables
  • C - Global Variables
  • C - Properties of Array
  • C - Multi-Dimensional Arrays
  • C - Passing Arrays to Function
  • C - Return Array from Function
  • C - Variable Length Arrays
  • C - Pointers
  • C - Pointers and Arrays
  • C - Applications of Pointers
  • C - Pointer Arithmetics
  • C - Array of Pointers
  • C - Passing Pointers to Functions
  • C - Strings
  • C - Array of Strings
  • C - Structures
  • C - Structures and Functions
  • C - Arrays of Structures
  • C - Pointers to Structures
  • C - Self-Referential Structures
  • C - Nested Structures
  • C - Bit Fields
  • C - Typedef
  • C - Input & Output
  • C - File I/O
  • C - Preprocessors
  • C - Header Files
  • C - Type Casting
  • C - Error Handling
  • C - Variable Arguments
  • C - Memory Management
  • C - Command Line Arguments
  • C Programming Resources
  • C - Questions & Answers
  • C - Quick Guide
  • C - Useful Resources
  • C - Discussion
  • Selected Reading
  • UPSC IAS Exams Notes
  • Developer's Best Practices
  • Questions and Answers
  • Effective Resume Writing
  • HR Interview Questions
  • Computer Glossary

Pointers in C

Pointers in C are easy and fun to learn. Some complex C programming tasks can be performed more easily with pointers, while some other tasks such as dynamic memory allocation cannot be performed without using pointers. So it becomes necessary to learn pointers to become a perfect C programmer.

With pointers, you can access and modify the data located in the memory, pass the data efficiently between the functions, and create dynamic data structures like linked lists, trees, and graphs.

Example: Address of the Variables

As you know, every variable is a memory location and every memory location has its address defined which can be accessed using the ampersand (&) operator, which denotes an address in memory.

Consider the following example, which prints the address of the variables defined −

When the above code is compiled and executed, it will print the address of the variables −

What are Pointers?

A pointer is a variable that stores the reference to another variable, which may be of any type such as int, float or char, an array (one or multidimensional), struct or union, or even a pointer type itself.

A pointer is a variable whose value is the address of another variable, i.e., the direct address of a memory location. Like any variable or constant, you must declare a pointer before using it to store any variable address. The general form of a pointer variable declaration is −

Here, type is the pointer's base type; it must be a valid C data type and var-name is the name of the pointer variable. The asterisk * used to declare a pointer is the same asterisk used for multiplication. However, in this statement the asterisk is being used to designate a variable as a pointer. Take a look at some of the valid pointer declarations −

The actual data type of the value of all pointers, whether integer, float, character, or otherwise, is the same, a long hexadecimal number that represents a memory address. The only difference between pointers of different data types is the data type of the variable or constant that the pointer points to.

Referencing and Dereferencing in C

A pointer references a location in memory. Obtaining the value stored at that location is known as dereferencing the pointer .

In C, it is important to understand the purpose of the following two operators in the context of pointer mechanism −

  • The & Operator − It is also known as the "Address-of operator". It is used for Referencing which means taking the address of an existing variable (using & ) to set a pointer variable.
  • The * Operator − It is also known as the "dereference operator". Dereferencing a pointer is carried out using the * operator to get the value from the memory address that is pointed by the pointer.

Pointers are used to pass parameters by reference. This is useful if a programmer wants a function's modifications to a parameter to be visible to the function's caller. This is also useful for returning multiple values from a function.

How to Use Pointers?

There are a few important operations, which we will do with the help of pointers very frequently. (a) We define a pointer variable, (b) assign the address of a variable to a pointer and (c) finally access the value at the address available in the pointer variable. This is done by using unary operator * that returns the value of the variable located at the address specified by its operand.

Example 1: Using Pointers in C

The following example shows how you can use the & and * operators to carry out pointer-related opeartions in C −

Execute the code and check its output −

To declare a pointer variable , the following syntax is to be used −

The name of the variable must be prefixed with an asterisk (*).

The data type indicates the type of variable the address of which it can store. For example, " int *x; ". Here, the variable "x" is meant to store the address of another int variable.

Similarly, in " float *y; the variable "y" is a pointer that stores the memory location of a float variable.

The & operator returns the address of an existing variable. We can assign it to the pointer variable. Take a look at the following code snippet −

Assuming that the compiler creates the variable "a" at the address 1000 and "x" at the address 2000, then the address of "a" is stored in "x".

variable at the address

The deference operator returns the value at the address stored in the pointer variable. Here "*x" will return the value of "a", i.e., the value stored in the memory address 1000, which in fact is the value of "x". Let us understand this with the help of the following example.

We will declare an int variable and display its value and address −

Run the code and check its output −

We can also use %p format specifier to obtain the hexadecimal number of the memory address.

In this example, the address of var is stored in the intptr variable with & operator

Now let's take an example of a float variable and find its address −

We can see that the address of this variable (any type of variable for that matter) is an integer. So, if we try to store it in a pointer variable of "float" type, see what happens −

The compiler doesn’t accept this, and reports the following error −

Note: The type of a variable and the type of its pointer must be same.

In C, variables have specific data types that define their size and how they store values. Declaring a pointer with a matching type (e.g., float *) enforces "type compatibility" between the pointer and the data it points to.

Different data types occupy different amounts of memory space in C. For example, an "int" typically takes 4 bytes, while a "float" might take 4 or 8 bytes depending on the system. Adding or subtracting integers from pointers moves them in memory based on the size of the data they point to.

In this example, we declare a variable "floatptr" of "float *" type.

The * operator is called the dereference operator. It returns the value of the variable that the pointer is pointing to.

Take a look at the following example −

We may have a pointer variable that stores the address of another pointer itself.

Pointer Variable

In the above figure, "a" is a normal "int" variable, whose pointer is "x". In turn, the variable stores the address of "x".

Note that "y" is declared as "int **" to indicate that it is a pointer to another pointer variable. Obviously, "y" will return the address of "x" and "*y" is the value in "x" (which is the address of "a").

To obtain the value of "a" from "y", we need to use the expression "**y". Usually, "y" will be called as the pointer to a pointer .

You can have a pointer to an array as well as a derived type defined with struct . Pointers have important applications. They are used while calling a function by passing the reference. Pointers also help in overcoming the limitation of a function’s ability to return only a single value. With pointers, you can get the effect of returning multiple values or arrays.

NULL Pointers

It is always a good practice to assign a NULL value to a pointer variable in case you do not have an exact address to be assigned. This is done at the time of variable declaration. A pointer that is assigned NULL is called a null pointer.

The NULL pointer is a constant with a value of "0" defined in several standard libraries.

Consider the following program −

When the above code is compiled and executed, it produces the following result −

In most operating systems, programs are not permitted to access memory at address "0" because that memory is reserved by the operating system.

The memory address "0" has a special significance; it signals that the pointer is not intended to point to an accessible memory location. But by convention, if a pointer contains the null (zero) value, it is assumed to point to nothing.

To check for a null pointer, you can use an if statement as follows −

Pointers in Detail

Pointers have many but easy concepts and they are very important to C programming. The following important pointer concepts should be clear to any C programmer −

To Continue Learning Please Login

Codeforwin

Pointer programming exercises and solutions in C

Pointer is a variable that stores memory addresses. Unlike normal variables it does not store user given or processed value, instead it stores valid computer memory address.

Pointer allows various magical things to be performed in C.

  • Pointers are more efficient in handling arrays and structures.
  • Pointers are used to return multiple values from a function.
  • Pointer allows dynamic memory allocation and deallocation (creation and deletion of variables at runtime) in C. Which undoubtedly is the biggest advantage of pointers.
  • Pointer allows to refer and pass a function as a parameter to functions.

and many more…

For beginners pointers can be a bad dream if not practiced well. However, once mastered you can do anything you want to do in C programming language.

In this exercise I will cover most of the pointer related topics from a beginner level. Always feel free to drop your queries and suggestion down below in the comments section .

Pointer to Pointer (Double pointer) memory representation

Required knowledge

Pointers , Pointer Arithmetic , Pointer to Pointer , Pointer and Arrays , Function Pointer

Please go through above tutorials to get a good grasp of following examples.

List of pointer programming exercises

  • Write a C program to create, initialize and use pointers .
  • Write a C program to add two numbers using pointers .
  • Write a C program to swap two numbers using pointers .
  • Write a C program to input and print array elements using pointer .
  • Write a C program to copy one array to another using pointers .
  • Write a C program to swap two arrays using pointers .
  • Write a C program to reverse an array using pointers .
  • Write a C program to search an element in array using pointers .
  • Write a C program to access two dimensional array using pointers .
  • Write a C program to add two matrix using pointers .
  • Write a C program to multiply two matrix using pointers .
  • Write a C program to find length of string using pointers .
  • Write a C program to copy one string to another using pointers .
  • Write a C program to concatenate two strings using pointers .
  • Write a C program to compare two strings using pointers .
  • Write a C program to find reverse of a string using pointers .
  • Write a C program to sort array using pointers .
  • Write a C program to return multiple value from function using pointers .

Learn C practically and Get Certified .

Popular Tutorials

Popular examples, reference materials, learn c interactively, introduction.

  • Getting Started with C
  • Your First C Program
  • C Variables, Constants and Literals
  • C Data Types
  • C Input Output (I/O)
  • C Programming Operators

Flow Control

  • C if...else Statement
  • C while and do...while Loop
  • C break and continue
  • C switch Statement
  • C goto Statement
  • C Functions
  • C User-defined functions
  • Types of User-defined Functions in C Programming
  • C Recursion
  • C Storage Class

Programming Arrays

  • C Multidimensional Arrays
  • Pass arrays to a function in C

Programming Pointers

  • Relationship Between Arrays and Pointers
  • C Pass Addresses and Pointers

C Dynamic Memory Allocation

  • C Array and Pointer Examples

Programming Strings

  • C Programming Strings
  • String Manipulations In C Programming Using Library Functions
  • String Examples in C Programming

Structure and Union

C structs and pointers.

C Structure and Function

Programming Files

  • C File Handling

C Files Examples

Additional Topics

  • C Keywords and Identifiers
  • C Precedence And Associativity Of Operators
  • C Bitwise Operators
  • C Preprocessor and Macros
  • C Standard Library Functions

C Tutorials

  • Store Data in Structures Dynamically
  • C Struct Examples
  • Store Information of Students Using Structure

Before you learn about how pointers can be used with structs, be sure to check these tutorials:

  • C Pointers to struct

Here's how you can create pointers to structs.

Here, ptr is a pointer to struct .

Example: Access members using Pointer

To access members of a structure using pointers, we use the -> operator.

In this example, the address of person1 is stored in the personPtr pointer using personPtr = &person1; .

Now, you can access the members of person1 using the personPtr pointer.

By the way,

  • personPtr->age is equivalent to (*personPtr).age
  • personPtr->weight is equivalent to (*personPtr).weight
  • Dynamic memory allocation of structs

Before you proceed this section, we recommend you to check C dynamic memory allocation .

Sometimes, the number of struct variables you declared may be insufficient. You may need to allocate memory during run-time. Here's how you can achieve this in C programming.

Example: Dynamic memory allocation of structs

When you run the program, the output will be:

In the above example, n number of struct variables are created where n is entered by the user.

To allocate the memory for n number of struct person , we used,

Then, we used the ptr pointer to access elements of person .

Table of Contents

  • Example: Access struct members using pointers

Sorry about that.

Related Tutorials

  • Overview of C
  • Features of C
  • Install C Compiler/IDE
  • My First C program
  • Compile and Run C program
  • Understand Compilation Process
  • C Syntax Rules
  • Keywords and Identifier
  • Understanding Datatypes
  • Using Datatypes (Examples)
  • What are Variables?
  • What are Literals?
  • Constant value Variables - const
  • C Input / Output
  • Operators in C Language
  • Decision Making
  • Switch Statement
  • String and Character array
  • Storage classes

C Functions

  • Introduction to Functions
  • Types of Functions and Recursion
  • Types of Function calls
  • Passing Array to function

C Structures

  • All about Structures
  • Pointers concept
  • Declaring and initializing pointer
  • Pointer to Pointer
  • Pointer to Array
  • Pointer to Structure
  • Pointer Arithmetic
  • Pointer with Functions

C File/Error

  • File Input / Output
  • Error Handling
  • Dynamic memory allocation
  • Command line argument
  • 100+ C Programs with explanation and output

Using Pointers in C

In this tutorial, we will learn how to declare, initialize and use a pointer in C language .

Before you continue, check these topics out:

Introduction to Pointers

C Loops - while , do while , for loops

A pointer is a variable used to store memory address. Hence, we have to declare and initialise(assign it a value) it just like any other variable. Pointers can be very useful in some use-cases, like:

  • They make accessing array elements easier.
  • We can implement linked lists, trees, and graphs using pointers.
  • We use pointers for accessing dynamically allocated memory.
  • We can return more than one value from a function using pointers.

So let's see how we can create pointers, assign values to pointers, perform pointer coversions, pointer arithmetic and pointer comparisons.

Declaring a Pointer in C

The general syntax of pointer declaration is,

Here, pointer_name is the name of the pointer and that should be a valid C identifier .

The datatype of the pointer and the variable to which the pointer variable is pointing must be the same.

Following are some examples of declaring a pointer in C:

Just like a variable, pointer is declared in the same way, just with an additional pointer operator * .

Assigning Value to a Pointer Variable

When we declare a pointer, it contains garbage value , which means it could be pointing anywhere in the memory. Pointer Initialization is the process of assigning the address of a variable to a pointer. In C language, the address operator & is used to determine the address of a variable. The & (immediately preceding a variable name) returns the address of the variable associated with it.

For example,

Value at ptr is: 10 Address pointed by ptr is: 0x7fff99c0e6c4

Run Code →

initialize pointer variable in C

Pointer variables must always point to variables of the same datatype.

For example, if we have a float type variable and an int type pointer, then C compiler will give error.

warning: assignment from incompatible pointer type ptr = &x; ^

While declaring a pointer variable, if it is not assigned to anything then it contains garbage value . And that can lead to unexpected errors in your program. Hence, it is recommended to assign a NULL value to it.

When we assign NULL to a pointer, it means that it does not point to any valid address. NULL denotes the value 'zero'.

set pointer variable value

A pointer that is assigned a NULL value is called a NULL pointer in C .

We can give a pointer a null value by assigning it zero to it. For example,

The above code will initialize the ptr pointer will a null value.

We can also use the NULL macro, which is nothing but a predefined constant for null pointer. This is defined in the <stdio.h> header library.

Pointer to Pointer Assignment in C

We can use an assignment operator to assign value of a pointer to another pointer variable. But for such assignment, types of both the pointer should be same.

Let's take a code example,

Value at p1 and p2: 10 10 Address pointed by p1 and p2: 0x7fff99c0e6c4 0x7fff99c0e6c4

As you can see in the code example above, multiple pointers can point to the same variable but they should be of the same data type.

Pointer Type Conversion in C

1. void * pointer.

The pointers of type void * are known as Generic pointers , and they can be assigned to any other type of pointer. Also, any other type of pointer can be assigned to a void * pointer.

2. Pointer type conversion

For pointer type other than void * , we have to explicitly cast pointer from one type to another. But this can lead to unexpected behaviour for incompatible datatypes.

For example, if we have a variable of type double , and we want to use a pointer of type int to point to this variable. Even after using explicit cast, the pointer will work as if it is pointing to a int type value. Now, a double type is of 8 bytes whereas an int type is of 4 bytes , hence, 4 bytes of information will be lost.

Let's see how we can use explicit cast for pointer conversion.

Value of a is: -858993459.000000

Pointer and Arrays

Derefrencing pointer in c.

Once a pointer has been assigned the address of a variable, the pointer is dereferenced , using the indirection operator or dereferencing operator , which is a * , to access the value of the variable.

For example, if we have,

Here is one complete program,

10 10 3795480300 3795480300 3795480304

Points to Remember while using Pointers

A pointer variable stores the address of a variable. We use * to declare and identify a pointer.

We can find the address of any variable using the & (ampersand) operator.

The declaration int *a doesn't mean that a is going to contain an integer value. It means that a is going to contain the address of a variable of int type.

We can dereference a pointer variable using a * operator. Here, the * can be read as 'value at' .

Since you have now learned the basics of Pointers in C, you can check out some C Pointer Programs where pointers are used for different use-cases.

Simple Pointer Program

Array of Pointer Program

What is Double Pointer?

Pointer with Function

  • ← Prev
  • Next →

Next: Assigning Function Pointers , Up: Function Pointers   [ Contents ][ Index ]

22.5.1 Declaring Function Pointers

The declaration of a function pointer variable (or structure field) looks almost like a function declaration, except it has an additional ‘ * ’ just before the variable name. Proper nesting requires a pair of parentheses around the two of them. For instance, int (*a) (); says, “Declare a as a pointer such that *a is an int -returning function.”

Contrast these three declarations:

The possible argument types of the function pointed to are the same as in a function declaration. You can write a prototype that specifies all the argument types:

or one that specifies some and leaves the rest unspecified:

or one that says there are no arguments:

You can also write a non-prototype declaration that says nothing about the argument types:

For example, here’s a declaration for a variable that should point to some arithmetic function that operates on two double s:

Structure fields, union alternatives, and array elements can be function pointers; so can parameter variables. The function pointer declaration construct can also be combined with other operators allowed in declarations. For instance,

declares foo as a pointer to a function that returns type int ** , and

declares foo as an array of 30 pointers to functions that return type int ** .

declares foo as a pointer to a pointer to a function that returns type int ** .

  • Skip to main content
  • Skip to primary sidebar
  • Skip to secondary sidebar
  • Skip to footer

Computer Notes

  • Computer Fundamental
  • Computer Memory
  • DBMS Tutorial
  • Operating System
  • Computer Networking
  • C Programming
  • C++ Programming
  • Java Programming
  • C# Programming
  • SQL Tutorial
  • Management Tutorial
  • Computer Graphics
  • Compiler Design
  • Style Sheet
  • JavaScript Tutorial
  • Html Tutorial
  • Wordpress Tutorial
  • Python Tutorial
  • PHP Tutorial
  • JSP Tutorial
  • AngularJS Tutorial
  • Data Structures
  • E Commerce Tutorial
  • Visual Basic
  • Structs2 Tutorial
  • Digital Electronics
  • Internet Terms
  • Servlet Tutorial
  • Software Engineering
  • Interviews Questions
  • Basic Terms
  • Troubleshooting

Header Right

How to pointer assignment and initialization in c.

By Dinesh Thakur

When we declare a pointer, it does not point to any specific variable. We must initialize it to point to the desired variable. This is achieved by assigning the address of that variable to the pointer variable, as shown below.

int a = 10;

pa = &a; /* pointer variable pa now points to variable a */

In this example, the first line declares an int variable named a and initializes it to 10. The second line declares a pointer pa of type pointer to int. Finally, the address of variable a is assigned to pa.Now pa is said to point to variable a.

We can also initialize a pointer when it is declared using the format given below.

type * ptr_var = init_expr ;

where init_expr is an expression that specifies the address of a previously defined variable of appropriate type or it can be NULL, a constant defined in the <stdio.h> header file.

Consider the example given below.

float x = 0.5;

float *px = &x;

int *p = NULL;

The second line declares a pointer variable px of type float * and initializes it with the address of variable x declared in the first line. Thus, pointer px now points to variable x. The third line declares pointer variable p of type int * and initializes it to NULL. Thus, pointer p does not point to any variable and it is an error to dereference such a pointer.

Note that a character pointer can be initialized using a character string constant as in

char *msg = “Hello, world!”;

Here, the C compiler allocates the required memory for the string constant (14 characters, in the above example, including the null terminator), stores the string constant in this memory and then assigns the initial address of this memory to pointer msg,as iliustrated in Fig.

pointer variable pointing to a string constant

The C language also permits initialization of more that one pointer variable in a single statement using the format shown below.

type *ptr_var1 = init_expr1, *ptr_var2 = init_expr2, … ;

It is also possible to mix the declaration and initialization of ordinary variables and pointers. However, we should avoid it to maintain program readability.

Example of Pointer Assignment and Initialization

char a= ‘A’;

char *pa = &a;

printf(“The address of character variable a: %p\n”, pa);

printf(“The address of pointer variable pa : %p\n”, &pa);

printf(“The value pointed by pointer variable pa: %c\n”, *pa);

Here, pa is a character pointer variable that is initialized with the address of character variable a defined in the first line. Thus, pa points to variable a. The first two printf statements print the address of variables a and pa using the %p (p for pointer) conversion. The last printf statement prints the value of a using the pointer variable pa. When the program containing this code is executed in Code::Blocks, the output is displayed as shown below. ·

The address of character variable a: 0022FF1F

The address of pointer variable pa : 0022FF18

The value pointed by pointer variable pa: A

Note that the addresses displayed in the output will usually be different depending on other variables declared in the program and the compiler/IDE used.

Another example is given below in which pointers are initialized with the addresses of variables of incompatible type.

char c = ‘Z’;

int i = 10;

float f = 1.1;

char *pcl = &i, *pc2 = &f;

int *pil = &c, *pi2 = &f;

float *pfl = &c, *pf2 = &i;

printf(“Character: %c %c\n”, *pcl, *pc2);

printf(“Integer : %d %d\n”, *pil, *pi2);

printf (“Float : %f %f\n”, =pfl, *pf2);

Note that the character pointer variables pcl and pc2 are initialized with the addresses of the int and float variables, respectively. Similarly, the int and float pointer variables are also initialized with addresses of variables of incompatible type. When the program containing this code is compiled in Code::Blocks, the compiler reports six warning messages (initialization from incompatible pointer type), one for each incompatible pointer initialization.

It is not a good idea to ignore such warnings associated with pointers. Although, the program executes in the presence of these warnings, it displays wrong results as shown below.

Integer : 90 1066192077

Float : 0.000000 0.000000

You’ll also like:

  • Write A C++ Program To Signify Importance Of Assignment (=) And Shorthand Assignment (+=) Operator.
  • Write C++ Example to illustrate two dimensional array implemented as pointer to a pointer.
  • Two-Dimensional Arrays Using a Pointer to Pointer
  • Declaration and Initialization of Pointers in C
  • Initialization of Two Dimensional Arrays Java

Dinesh Thakur

Dinesh Thakur is a Freelance Writer who helps different clients from all over the globe. Dinesh has written over 500+ blogs, 30+ eBooks, and 10000+ Posts for all types of clients.

For any type of query or something that you think is missing, please feel free to Contact us .

Basic Course

  • Database System
  • Management System
  • Electronic Commerce

Programming

  • Structured Query (SQL)
  • Java Servlet

World Wide Web

  • Java Script
  • HTML Language
  • Cascading Style Sheet
  • Java Server Pages
  • C Data Types
  • C Operators
  • C Input and Output
  • C Control Flow
  • C Functions
  • C Preprocessors
  • C File Handling
  • C Cheatsheet
  • C Interview Questions
  • Pointer Arithmetics in C with Examples
  • Applications of Pointers in C
  • Passing Pointers to Functions in C
  • C - Pointer to Pointer (Double Pointer)
  • Chain of Pointers in C with Examples

Function Pointer in C

  • How to declare a pointer to a function?
  • Pointer to an Array | Array Pointer
  • Difference between constant pointer, pointers to constant, and constant pointers to constants
  • Pointer vs Array in C
  • NULL Pointer in C
  • Dangling, Void , Null and Wild Pointers in C
  • Near, Far and Huge Pointers in C
  • restrict keyword in C

In C, like normal data pointers (int *, char *, etc), we can have pointers to functions. Following is a simple example that shows declaration and function call using function pointer.

Why do we need an extra bracket around function pointers like fun_ptr in above example? If we remove bracket, then the expression “void (*fun_ptr)(int)” becomes “void *fun_ptr(int)” which is declaration of a function that returns void pointer. See following post for details. How to declare a pointer to a function?

Following are some interesting facts about function pointers.

  1) Unlike normal pointers, a function pointer points to code, not data. Typically a function pointer stores the start of executable code.

2) Unlike normal pointers, we do not allocate de-allocate memory using function pointers.

  3) A function’s name can also be used to get functions’ address. For example, in the below program, we have removed address operator ‘&’ in assignment. We have also changed function call by removing *, the program still works.

  4) Like normal pointers, we can have an array of function pointers. Below example in point 5 shows syntax for array of pointers.

  5) Function pointer can be used in place of switch case. For example, in below program, user is asked for a choice between 0 and 2 to do different tasks.

  6) Like normal data pointers, a function pointer can be passed as an argument and can also be returned from a function. For example, consider the following C program where wrapper() receives a void fun() as parameter and calls the passed function.

This point in particular is very useful in C. In C, we can use function pointers to avoid code redundancy. For example a simple qsort() function can be used to sort arrays in ascending order or descending or by any other order in case of array of structures. Not only this, with function pointers and void pointers, it is possible to use qsort for any data type.

Similar to qsort(), we can write our own functions that can be used for any data type and can do different tasks without code redundancy. Below is an example search function that can be used for any data type. In fact we can use this search function to find close elements (below a threshold) by writing a customized compare function.

The above search function can be used for any data type by writing a separate customized compare().

  7) Many object oriented features in C++ are implemented using function pointers in C. For example virtual functions . Class methods are another example implemented using function pointers. Refer this book for more details.

Related Article: Pointers in C and C++ | Set 1 (Introduction, Arithmetic and Array)

References: http://www.cs.cmu.edu/~ab/15-123S11/AnnotatedNotes/Lecture14.pdf

http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-087-practical-programming-in-c-january-iap-2010/lecture-notes/MIT6_087IAP10_lec08.pdf

http://www.cs.cmu.edu/~guna/15-123S11/Lectures/Lecture14.pdf

Please Login to comment...

Similar reads.

  • CPP-Functions
  • cpp-pointer

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

IMAGES

  1. Pointer Expressions in C with Examples

    pointers assignment in c

  2. C Pointers

    pointers assignment in c

  3. Pointer Expressions in C with Examples

    pointers assignment in c

  4. Pointer Expressions in C with Examples

    pointers assignment in c

  5. Pointer Expressions in C with Examples

    pointers assignment in c

  6. Pointer Expressions in C with Examples

    pointers assignment in c

VIDEO

  1. 1. Introduction to Pointers in C

  2. C Programming

  3. Introduction to Programming in C Week 2 Assignment Answers 2024 |@OPEducore

  4. What are Pointers? How to Use Them? and How they can Improve your C++ Programming Skills

  5. What are Pointers? How to Use Them? and How they can Improve your C++ Programming Skills

  6. Pointers concept and assignment of addresses

COMMENTS

  1. C Pointers

    The use of pointers in C can be divided into three steps: Pointer Declaration. Pointer Initialization. Pointer Dereferencing. 1. Pointer Declaration. In pointer declaration, we only declare the pointer but do not initialize it. To declare a pointer, we use the ( * ) dereference operator before its name. Example.

  2. C Pointers (With Examples)

    Explanation of the program. int* pc, c; Here, a pointer pc and a normal variable c, both of type int, is created. Since pc and c are not initialized at initially, pointer pc points to either no address or a random address. And, variable c has an address but contains random garbage value.; c = 22; This assigns 22 to the variable c.That is, 22 is stored in the memory location of variable c.

  3. How C-Pointers Works: A Step-by-Step Beginner's Tutorial

    To declare and initialize a pointer to a pointer, you need to add an extra asterisk (*) compared to a regular pointer. Let's go through an example: int x = 10; int *ptr1 = &x; // Pointer to an integer int **ptr2 = &ptr1; // Pointer to a pointer to an integer. In this example, ptr2 is a pointer to a pointer.

  4. Pointers in C Explained

    4. Strings. A string is a one-dimensional array of characters terminated by a null(\0).When we write char name[] = "Srijan";, each character occupies one byte of memory with the last one always being \0.. Similar to the arrays we have seen, name and &name[0] points to the 0th character in the string, while &name points to the whole string. Also, name[i] can be written as *(name + i).

  5. How to Use Pointers in C Programming

    How to Declare a Pointer. To declare a pointer variable in C, we use the asterisk * symbol before the variable name. There are two ways to declare pointer variables in C: int *p; int* p; Both of these declarations are equivalent and they declare a pointer variable named "p" that can hold the memory address of an integer.

  6. C Pointers

    Good To Know: There are two ways to declare pointer variables in C: int* myNum; int *myNum; Notes on Pointers. Pointers are one of the things that make C stand out from other programming languages, like Python and Java. They are important in C, because they allow us to manipulate the data in the computer's memory.

  7. (Almost) Everything You Need To Know About Pointers in C

    char *pa = &a; // pa now contains the address of a. printf("%p", pa); // %p is the format specifier to print a pointer. If you run this program, you will see something like 0x7ffc2fc4ff27. That is the value of the pointer, which is the address of the variable a (this is in hexadecimal). This value is not fixed.

  8. Pointer Basics

    Pointer Basics. This document introduces the basics of pointers as they work in several computer languages -- C, C++, Java, and Pascal. This document is the companion document for the Pointer Fun with Binky digital video, or it may be used by itself. This is document 106 in the Stanford CS Education Library.

  9. Pointer Expressions in C with Examples

    When we need to initialize a pointer with variable's location, we use ampersand sign (&) before the variable name. Example: C. int var=10; int *pointer=&var; The ampersand (&) is used to get the address of a variable. We can directly find the location of any identifier by just preceding it with an ampersand (&) sign.

  10. Pointers in C

    The general form of a pointer variable declaration is −. type * var - name; Here, type is the pointer's base type; it must be a valid C data type and var-name is the name of the pointer variable. The asterisk * used to declare a pointer is the same asterisk used for multiplication.

  11. Pointer Arithmetics in C with Examples

    Note: Pointers can be outputted using %p, since, most of the computers store the address value in hexadecimal form using %p gives the value in that form. But for simplicity and understanding we can also use %u to get the value in Unsigned int form. 2. Addition of Integer to Pointer. When a pointer is added with an integer value, the value is first multiplied by the size of the data type and ...

  12. Pointers in C

    Pointers are more efficient in handling arrays and structures. Pointers are used to return multiple values from a function. We use pointers to get reference of a variable or function. Pointer allows dynamic memory allocation (creation of variables at runtime) in C. Which undoubtedly is the biggest advantage of pointers.

  13. Pointer programming exercises and solutions in C

    Pointer allows various magical things to be performed in C. Pointers are more efficient in handling arrays and structures. Pointers are used to return multiple values from a function. Pointer allows dynamic memory allocation and deallocation (creation and deletion of variables at runtime) in C. Which undoubtedly is the biggest advantage of ...

  14. C structs and Pointers (With Examples)

    printf("weight: %f", personPtr->weight); return 0; } Run Code. In this example, the address of person1 is stored in the personPtr pointer using personPtr = &person1;. Now, you can access the members of person1 using the personPtr pointer. By the way, personPtr->age is equivalent to (*personPtr).age. personPtr->weight is equivalent to ...

  15. c

    Third, by increasing the value of a pointer, you're incrementing it by the sizeof its contents, that is you're incrementing it as if you were iterating in an array. So, to sum it all up: *ptr++; // Pointer moves to the next int position (as if it was an array). But returns the old content.

  16. CS31: Intro to C Structs and Pointers

    C Stucts and Pointers. This is the second part of a two part introduction to the C programming language. It is written specifically for CS31 students. The first part covers C programs, compiling and running, variables, types, operators, loops, functions, arrays, parameter passing (basic types and arrays), standard I/O (printf, scanf), and file ...

  17. Using Pointers in C

    The general syntax of pointer declaration is, type *pointer_name; Here, pointer_name is the name of the pointer and that should be a valid C identifier. The datatype of the pointer and the variable to which the pointer variable is pointing must be the same. Following are some examples of declaring a pointer in C:

  18. Declaring Function Pointers (GNU C Language Manual)

    The declaration of a function pointer variable (or structure field) looks almost like a function declaration, except it has an additional ' * ' just before the variable name. Proper nesting requires a pair of parentheses around the two of them. For instance, int (*a) (); says, "Declare a as a pointer such that *a is an int -returning ...

  19. How to Pointer Assignment and Initialization in C

    This is achieved by assigning the address of that variable to the pointer variable, as shown below. int a = 10; int *pa; pa = &a; /* pointer variable pa now points to variable a */. In this example, the first line declares an int variable named a and initializes it to 10. The second line declares a pointer pa of type pointer to int.

  20. assignment of arrays to pointers in C

    By C's rule about automatic conversion of arrays, in t.text = arr;, arr is converted to a pointer to its first element. So we have t.text = &arr[0];. Then &arr[0] is a pointer to a pointer to a char, and t.text is a pointer to a pointer to a char, so the types are compatible. edited Dec 28, 2018 at 13:13.

  21. Function Pointer in C

    2) Unlike normal pointers, we do not allocate de-allocate memory using function pointers. 3) A function's name can also be used to get functions' address. For example, in the below program, we have removed address operator '&' in assignment. We have also changed function call by removing *, the program still works.

  22. pointer to pointer assignment in c

    new is pointing to one byte past the last element of whatever was copied over from s1.You should pass the pointer to the first element of new to get the entire text.. Another problem is that you are not copying over the \0 from s1 to new.You should put a \0 at the end of new before trying to print it. Otherwise you are invoking UB.. You might do something like this and check: