DEV Community

DEV Community

AbdulKarim

Posted on Oct 29, 2023

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

In this comprehensive C Pointers tutorial, my primary goal is to guide you through the fundamentals of C pointers from the ground up. By the end of this tutorial, you will have gained an in-depth understanding of the following fundamental topics:

  • What is a Pointer?
  • How Data is Stored in Memory?
  • Storing Memory Addresses using Pointers

Accessing Data through Pointers

  • Pointer Arithmetic
  • Pointer to Pointer (Double Pointers)
  • Passing Pointers as Function Arguments

Arrays of Pointers

Null pointers, prerequisite:.

To grasp pointers effectively, you should be comfortable with basic C programming concepts, including variables, data types, functions, loops, and conditional statements. This familiarity with C programming forms the foundation for understanding how pointers work within the language. Once you have a solid grasp of these fundamental concepts, you can confidently delve into the intricacies of C pointers.

What is a pointer?

A pointer serves as a reference that holds the memory location of another variable. This memory address allows us to access the value stored at that location in the memory. You can think of a pointer as a way to reference or point to the location where data is stored in your computer's memory

Pointers can be a challenging concept for beginners to grasp, but in this tutorial, I'll explain them using real-life analogies to make the concept clearer. However, Before delving into pointers and their workings, it's important to understand the concept of a memory address.

A memory address is a unique identifier that points to a specific location in a computer's memory. Think of it like a street address for data stored in your computer's RAM (Random Access Memory). Just as a street address tells you where a particular house is located in the physical world, a memory address tells the computer where a specific piece of information or data is stored in its memory.

Take a look at the image below for a better understanding:

Block of memory

In this illustration, each block represents one byte of memory. It's important to note that every byte of memory has a unique address. To make it easier to understand, I've represented the addresses in decimal notation, but computers actually store these addresses using hexadecimal values. Hexadecimal is a base-16 numbering system commonly used in computing to represent memory addresses and other low-level data. It's essential to be aware of this representation when working with memory-related concepts in computer programming

How data is stored in the memory:

Every piece of data in your computer, whether it's a number, a character, or a program instruction, is stored at a specific memory address. The amount of space reserved for each data type can vary, and it is typically measured in bytes (where 1 byte equals 8 bits, with each bit representing either 0 or 1). The specific sizes of data types also depend on the computer architecture you are using. For instance, on most 64-bit Linux machines, you'll find the following typical sizes for common data types: char = 1 byte int = 4 bytes float = 4 bytes double = 8 bytes These sizes define how much memory each data type occupies and are crucial for memory management and efficient data representation in computer systems.

You can use the sizeof operator to determine the size of data types on your computer. example:

In this example: sizeof(char) returns the size of the char data type in bytes. sizeof(int) returns the size of the int data type in bytes. sizeof(float) returns the size of the float data type in bytes. sizeof(double) returns the size of the double data type in bytes. When you run this code, it will print the sizes of these data types on your specific computer, allowing you to see the actual sizes used by your system.

When you declare a variable, the computer allocates a specific amount of memory space corresponding to the chosen data type. For instance, when you declare a variable of type char, the computer reserves 1 byte of memory because the size of the 'char' data type is conventionally 1 byte.

address of char n

In this example, we declare a variable n of type char without assigning it a specific value. The memory address allocated for the n variable is 106 . This address, 106 , is where the computer will store the char variable n, but since we haven't assigned it a value yet, the content of this memory location may initially contain an unpredictable or uninitialized value.

When we assign the value 'C' to the variable n, the character 'C' is stored in the memory location associated with the variable n. When we assign the value 'C' to the variable n, the character 'C' is stored in the memory location associated with the variable n.

address of cahr n = c

As mentioned earlier, a byte can only store numerical values. When we store the letter 'C' in a byte, the byte actually holds the ASCII code for 'C,' which is 67. In computer memory, characters are represented using their corresponding ASCII codes. So, in memory, the character 'C' is stored as the numerical value 67. Here's how it looks in memory

Ascii code of c

Since integers are typically stored within four bytes of memory, let's consider the same example with an int variable. In this scenario, the memory structure would appear as follows:

add. of int t

In this example, the memory address where the variable t is stored is 121. An int variable like “t” typically uses four consecutive memory addresses, such as 121, 122, 123, and 124. The starting address, in this case, 121, represents the location of the first byte of the int, and the subsequent addresses sequentially represent the following bytes that collectively store the complete int value.

If you want to know the memory address of a variable in a program, you can use the 'address of' unary operator, often denoted as the '&' operator. This operator allows you to access the specific memory location where a variable is stored.

When you run the following program on your computer: It will provide you with specific memory addresses for the variables c and n. However, each time you rerun the program, it might allocate new memory addresses for these variables. It's important to understand that while you can determine the memory address of a variable using the & operator, the exact memory location where a variable is stored is typically managed by the system and the compiler. As a programmer, you cannot directly control or assign a specific memory location for a variable. Instead, memory allocation and management are tasks handled by the system and the compiler.

Storing memory address using pointers

As mentioned earlier, a pointer is a variable that stores the memory address of another variable. This memory address allows us to access the value stored at that location in memory. You can think of a pointer as a way to reference or point to the location where data is stored in your computer's memory.

Now, let's begin by declaring and initializing pointers. This step is essential because it sets up the pointer to hold a specific memory address, enabling us to interact with the data stored at that location.

Declaring Pointers: To declare a pointer, you specify the data type it points to, followed by an asterisk (*), and then the pointer's name. For example:

Here, we've declared a pointer named ptr that can point to integers.

Memory of Declaring an integer pointer

The size of pointers on 64-bit systems is usually 8 bytes (64 bits). To determine the pointer size on your system, you can use the sizeof operator:

Initializing Pointers: Once you've declared a pointer, you typically initialize it with the memory address it should point to. Once again, To obtain the memory address of a variable, you can employ the address-of operator (&). For instance:

In this program:

We declare an integer variable x and initialize it with the value 10. This line creates a variable x in memory and assigns the value 10 to it.

ptr

We declare an integer pointer ptr using the int *ptr syntax. This line tells the compiler that ptr will be used to store the memory address of an integer variable.

pointrt to ptr

We initialize the pointer ptr with the memory address of the variable x . This is achieved with the line ptr = &x; . The & operator retrieves the memory address of x, and this address is stored in the pointer ptr .

address of variable x

Dereferencing Pointers: To access the data that a pointer is pointing to, you need to dereference the pointer. Dereferencing a pointer means accessing the value stored at the memory address that the pointer points to. In C, you can think of pointers as variables that store memory addresses rather than actual values. To get the actual value (data) stored at that memory address, you need to dereference the pointer.

Dereferencing is done using the asterisk (*) operator. Here's an example:

It looks like this in the memory: int x = 10; variable 'x' stores the value 10:

var X

int *ptr = &x; Now, the pointer 'ptr' point to the address of 'x':

Pointer to X

int value = *ptr; Dereference 'ptr' to get the value stored at the address it points to:

pointer value is 10

Reading and Modifying Data: Pointers allow you to not only read but also modify data indirectly:

Note: The asterisk is a versatile symbol with different meanings depending on where it's used in your C program, for example: Declaration: When used during variable declaration, the asterisk (*) indicates that a variable is a pointer to a specific data type. For example: int *ptr; declares 'ptr' as a pointer to an integer.

Dereferencing: Inside your code, the asterisk (*) in front of a pointer variable is used to access the value stored at the memory address pointed to by the pointer. For example: int value = *ptr; retrieves the value at the address 'ptr' points to.

Pointer Arithmetic:

Pointer arithmetic is the practice of performing mathematical operations on pointers in C. This allows you to navigate through arrays, structures, and dynamically allocated memory. You can increment or decrement pointers, add or subtract integers from them, and compare them. It's a powerful tool for efficient data manipulation, but it should be used carefully to avoid memory-related issues.

Incrementing a Pointer:

Now, this program is how it looks in the memory: int arr[4] = {10, 20, 30, 40};

int arr

This behavior is a key aspect of pointer arithmetic. When you add an integer to a pointer, it moves to the memory location of the element at the specified index, allowing you to efficiently access and manipulate elements within the array. It's worth noting that you can use pointer arithmetic to access elements in any position within the array, making it a powerful technique for working with arrays of data. Now, let's print the memory addresses of the elements in the array from our previous program.

If you observe the last two digits of the first address is 40, and the second one is 44. You might be wondering why it's not 40 and 41. This is because we're working with an integer array, and in most systems, the size of an int data type is 4 bytes. Therefore, the addresses are incremented in steps of 4. The first address shows 40, the second 44, and the third one 48

Decrementing a Pointer Decrement (--) a pointer variable, which makes it point to the previous element in an array. For example, ptr-- moves it to the previous one. For example:

Explanation:

We have an integer array arr with 5 elements, and we initialize a pointer ptr to point to the fourth element (value 40) using &arr[3].

Then, we decrement the pointer ptr by one with the statement ptr--. This moves the pointer to the previous memory location, which now points to the third element (value 30).

Finally, we print the value pointed to by the decremented pointer using *ptr, which gives us the value 30.

In this program, we demonstrate how decrementing a pointer moves it to the previous memory location in the array, allowing you to access and manipulate the previous element.

Pointer to pointer

Pointers to pointers, or double pointers, are variables that store the address of another pointer. In essence, they add another level of indirection. These are commonly used when you need to modify the pointer itself or work with multi-dimensional arrays.

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:

In this example, ptr2 is a pointer to a pointer. It points to the memory location where the address of x is stored (which is ptr1 ).

pointer to poiter

The below program will show you how to print the value of x through pointer to pointer

In this program, we first explain that it prints the value of x using a regular variable, a pointer, and a pointer to a pointer. We then print the memory addresses of x , ptr1 , and ptr2 .

Passing Pointers as Function Arguments:

In C, you can pass pointers as function arguments. This allows you to manipulate the original data directly, as opposed to working with a copy of the data, as you would with regular variables. Here's how it works:

How to Declare and Define Functions that Take Pointer Arguments: In your function declaration and definition, you specify that you're passing a pointer by using the * operator after the data type. For example:

In the above function, we declare ptr as a pointer to an integer. This means it can store the memory address of an integer variable.

Why Would You Pass Pointers to Functions?

Passing pointers to functions allows you to:

  • Modify the original data directly within the function.
  • Avoid making a copy of the data, which can be more memory-efficient.
  • Share data between different parts of your program efficiently.

This concept is especially important when working with large data structures or when you need to return multiple values from a function.

Call by Value vs. Call by Reference:

Understanding how data is passed to functions is crucial when working with pointers. there are two common ways that data can be passed to functions: call by value and call by reference.

Call by Value:

When you pass data by value, a copy of the original data is created inside the function. Any modifications to this copy do not affect the original data outside of the function. This is the default behavior for most data types when you don't use pointers.

Call by Reference (Using Pointers):

When you pass data by reference, you're actually passing a pointer to the original data's memory location. This means any changes made within the function will directly affect the original data outside the function. This is achieved by passing pointers as function arguments, making it call by reference. Using pointers as function arguments allows you to achieve call by reference behavior, which is particularly useful when you want to modify the original data inside a function and have those changes reflected outside the function.

Let's dive into some code examples to illustrate how pointers work as function arguments. We'll start with a simple example to demonstrate passing a pointer to a function and modifying the original data.

Consider this example:

In this code, we define a function modifyValue that takes a pointer to an integer. We pass the address of the variable num to this function, and it doubles the value stored in num directly.

This is a simple demonstration of passing a pointer to modify a variable's value. Pointers allow you to work with the original data efficiently.

An array of pointers is essentially an array where each element is a pointer. These pointers can point to different data types (int, char, etc.), providing flexibility and efficiency in managing memory.

How to Declare an Array of Pointers? To declare an array of pointers, you specify the type of data the pointers will point to, followed by square brackets to indicate it's an array, and then the variable name. For example:

Initializing an Array of Pointers You can initialize an array of pointers to each element to point to a specific value, For example:

How to Access Elements Through an Array of Pointers? To access elements through an array of pointers, you can use the pointer notation. For example:

This program demonstrates how to access and print the values pointed to by the pointers in the array.

A NULL pointer is a pointer that lacks a reference to a valid memory location. It's typically used to indicate that a pointer doesn't have a specific memory address assigned, often serving as a placeholder or default value for pointers.

Here's a code example that demonstrates the use of a NULL pointer:

In this example, we declare a pointer ptr and explicitly initialize it with the value NULL. We then use an if statement to check if the pointer is NULL. Since it is, the program will print "The pointer is NULL." This illustrates how NULL pointers are commonly used to check if a pointer has been initialized or assigned a valid memory address.

conclusion:

You've embarked on a comprehensive journey through the intricacies of C pointers. You've learned how pointers store memory addresses, enable data access, facilitate pointer arithmetic, and how they can be used with arrays and functions. Additionally, you've explored the significance of NULL pointers.

By completing this tutorial, you've equipped yourself with a robust understanding of pointers in C. You can now confidently navigate memory, manipulate data efficiently, and harness the power of pointers in your programming projects. These skills will be invaluable as you advance in your coding endeavors. Congratulations on your accomplishment, and keep coding with confidence!

Reference: C - Pointers - Tutorials Point

Pointers in C: A One-Stop Solution for Using C Pointers - simplilearn

Top comments (3)

pic

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

imperiald profile image

  • Joined Jan 7, 2024

Love your way to write articles, could you add an article for, .o files, .h files, lists and makefile? Thank you in advance!

cocomelonjuice profile image

  • Joined Nov 4, 2023

Great post. Thank you so much for this.

koderkareem profile image

Thank you for your kind words! I'm thrilled to hear that you enjoyed the article. Your feedback means a lot to me. If you have any questions or if there's a specific topic you'd like to see in future posts, feel free to let me know. Thanks again for your support

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

bcostaaa01 profile image

Vue Composables: what are they, and how to create & use one

Bruno - Mar 29

nickytonline profile image

Form and Function: How I Lost My Submit Button & Got It Back

Nick Taylor - Apr 2

envitab profile image

How to build: a v0.dev clone (Next.js, GPT4 & CopilotKit)

Ekemini Samuel - Apr 4

riddhesh profile image

CI/CD Pipeline for React Native

Riddhesh - Mar 15

DEV Community

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

Learn C practically and Get Certified .

Popular Tutorials

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

  • Keywords & Identifier
  • Variables & Constants
  • C Data Types
  • C Input/Output
  • C Operators
  • C Introduction Examples

C Flow Control

  • C if...else
  • C while Loop
  • C break and continue
  • C switch...case
  • C Programming goto
  • Control Flow Examples

C Functions

  • C Programming Functions
  • C User-defined Functions
  • C Function Types
  • C Recursion
  • C Storage Class
  • C Function Examples
  • C Programming Arrays
  • C Multi-dimensional Arrays
  • C Arrays & Function
  • C Programming Pointers
  • C Pointers & Arrays
  • C Pointers And Functions
  • C Memory Allocation
  • Array & Pointer Examples

C Programming Strings

  • C Programming String
  • C String Functions
  • C String Examples

Structure And Union

  • C Structure
  • C Struct & Pointers
  • C Struct & Function
  • C struct Examples

C Programming Files

  • C Files Input/Output
  • C Files Examples

Additional Topics

  • C Enumeration
  • C Preprocessors
  • C Standard Library
  • C Programming Examples

Relationship Between Arrays and Pointers

C Pass Addresses and Pointers

C structs and Pointers

  • Access Array Elements Using Pointer

C Dynamic Memory Allocation

  • C Array and Pointer Examples

Pointers are powerful features of C and C++ programming. Before we learn pointers, let's learn about addresses in C programming.

  • Address in C

If you have a variable var in your program, &var will give you its address in the memory.

We have used address numerous times while using the scanf() function.

Here, the value entered by the user is stored in the address of var variable. Let's take a working example.

Note: You will probably get a different address when you run the above code.

Pointers (pointer variables) are special variables that are used to store addresses rather than values.

Pointer Syntax

Here is how we can declare pointers.

Here, we have declared a pointer p of int type.

You can also declare pointers in these ways.

Let's take another example of declaring pointers.

Here, we have declared a pointer p1 and a normal variable p2 .

  • Assigning addresses to Pointers

Let's take an example.

Here, 5 is assigned to the c variable. And, the address of c is assigned to the pc pointer.

Get Value of Thing Pointed by Pointers

To get the value of the thing pointed by the pointers, we use the * operator. For example:

Here, the address of c is assigned to the pc pointer. To get the value stored in that address, we used *pc .

Note: In the above example, pc is a pointer, not *pc . You cannot and should not do something like *pc = &c ;

By the way, * is called the dereference operator (when working with pointers). It operates on a pointer and gives the value stored in that pointer.

  • Changing Value Pointed by Pointers

We have assigned the address of c to the pc pointer.

Then, we changed the value of c to 1. Since pc and the address of c is the same, *pc gives us 1.

Let's take another example.

Then, we changed *pc to 1 using *pc = 1; . Since pc and the address of c is the same, c will be equal to 1.

Let's take one more example.

Initially, the address of c is assigned to the pc pointer using pc = &c; . Since c is 5, *pc gives us 5.

Then, the address of d is assigned to the pc pointer using pc = &d; . Since d is -15, *pc gives us -15.

  • Example: Working of Pointers

Let's take a working example.

Explanation of the program

A pointer variable and a normal variable is created.

Common mistakes when working with pointers

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

Here's an example of pointer syntax beginners often find confusing.

Why didn't we get an error when using int *p = &c; ?

It's because

is equivalent to

In both cases, we are creating a pointer p (not *p ) and assigning &c to it.

To avoid this confusion, we can use the statement like this:

Now you know what pointers are, you will learn how pointers are related to arrays in the next tutorial.

Table of Contents

  • What is a pointer?
  • Common Mistakes

Sorry about that.

Related Tutorials

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

Chapter 8: Pointers and Memory Allocation

We have discussed many abstractions that are built into the C programming language. Most of these abstractions intentionally obscure something central to storage: the address in memory where something is stored. Pointers are a way to get closer to memory and to manipulate the contents of memory directly.

In this chapter, we will discuss pointers and how pointers are used to work with memory. We will discuss how memory can be dynamically allocated and manipulated using pointers. And we will see that arrays and pointer are very closely connected.

Pointer Basics

We know variables in C are abstractions of memory, holding a value. That value is typed , defined by a data type definition in the variable declaration.

A pointer is no different. A pointer is a variable whose value is an address, typed by its declaration. Pointers "point to" a variable (memory) with a typed value by referencing that variable, not by name, but by address.

Declarations

Pointers are declared to point to a typed value. This is the syntax of a declaration:

Here are some examples:

These declare ptr1 to hold the address of an integer, ptr2 to hold the address of a floating point number, and ptr3 to hold the address of a character.

Like all variables, pointer variables do not have a value simply by being declared . That fact might seem intuitive for other data types, but it's hard to remember for pointers. In the above examples, the variables are meant to contain the address of other variables, but they have not been initialized yet.

Declaration Notation At first glance, the notation used to declare pointers might seem wrong. Since a pointer variable points to another variable of the declared data type, you might expect the declaration to look like this: int* ptr1; Instead, the * symbol is associated with the variable name in the declaration. This is intentional. If we associate the * symbol with the variable name, we can declare a list of variable names, some of which are not pointers. Here is an example: int *ptr1, width, height, *mem; Note that not everything in the list is a pointer. This is possible only if we associate the * with the variable name. If we were to use the notation int* ptr1, mem; only the first item in the list would be a pointer.

Variables and Addresses

If pointers contain addresses, there should be a way to give them an address as a value. All variables have an address, a designation of where they are stored in memory. We can derive the address of a variable by placing a "&" symbol in front of the variable name. Here is an example:

The variable ptri is assigned the address of the variable distance as its value. The value of distance is not changed.

Now if we were to print the value of ptri , we would get a large number that really makes no sense to us , but makes sense to the computer runtime system. The printf function call above might print this as its value:

That value makes sense to the computer, but it is of no use to programmers. Knowing the address does not help us work with the pointer or what it points to.

Dereferencing a Pointer

Once a pointer has an address of a variable name, we can use it to work with the variable it references. To do this, we have to dereference the pointer, that is, get to the variable or memory it points to.

Dereferencing a pointer uses the same asterisk notation that we used to declare a pointer. Consider the following example.

This code starts by assigning the value 10 to the variable payment . Then the pointer p takes the address of payment as its value. The third statement changes payment to 15 by actually assigning the value 15 to the variable to which p points. The *p in the statement is a dereference.

Using the same syntax to declare pointers and to dereference pointers can be a bit confusing, especially if the declaration is used with an initial value, like in the above example. Unfortunately, you just have to remember the difference between declaration and dereferencing.

Let's look at one more example of dereferencing.

In this example, the variable distance is set to 250 and incremented by 10 by dereferencing the pointer pd . Likewise, the variable fuel is set to 10 , then incremented by 5 by dereferencing the pointer pf . The last statement is there to show that you can even dereference an address operator. By dereferencing what the address of economy2 points to, we just reference the variable economy2 .

Allocating Memory

While you can work with declared variables using the "&" operator, you can also create memory space while a program is executing and allow a pointer to reference it. This memory space does not even need a name associated with it.

You create space in memory using the malloc function. To create space, you need to know the type of space you want to create and the size in bytes of that space. Fortunately, you don't have to know the size of everything in C; you can use an operator to compute that.

The sizeof operator will return the number of bytes its type parameter uses. For example,

should return the value 4 : a variable declared to be of type int will take up 4 bytes in memory.

Once we know the number of bytes we want to allocate, calling malloc with the right size will create a space in memory of that size and will return the address of that space. So, consider this example:

Here, we have allocated enough memory to store a single integer and returned the address of that space to be assigned to the pointer p . Now, the only way to work with that space is through the pointer. But if we use dereferencing correctly, this space can be used as if we have a variable, because we do! We do indeed have a variable; it just does not have a name associated with it.

Here's another example:

In this allocation, we have created a space that is big enough to store 5 integers.

Since this space is contiguous, that is, created from sequential memory locations, we have essentially created an array of 5 integers. We will examine this further, but we need to first figure out how to access each integer in this space by doing arithmetic on pointers.

Pointers are typed in C. When a pointer is declared, the data type it points to is recorded. As with other variables, if we try to assign values from incompatible types, errors will result.

Pointer Arithmetic

We have said that a pointer contains an address into memory. If addresses are just numbers, then we can do computations with them. Indeed, we can do pointer arithmetic in an intuitive fashion.

As you might think, pointer arithmetic uses operators + and - to increment or decrement addresses. However, to increment a pointer means to add enough to its value to move to the next element of the data type to which it points. For example, if a pointer contains the address of an integer, then adding one to that pointer means skipping 4 bytes to point to the next integer. If the data type is larger, the increment will increase the pointer the correct amount of bytes. Decrement works in an analogous way.

This is especially useful when a pointer points to the beginning of an allocated area in memory. Let's say that we have code that just allocated space in memory for 20 integers:

By dereferencing the pointer, we gain access to the first integer in the space. The rest of the integers are accessible through pointer arithmetic. Consider the following code:

This code assigns the values 20 and 30 to the the second and third integers in the space, respectively. This is how we would access all integers in the allocated space.

There's a few notes we need to make about pointer arithmetic.

  • The result of pointer arithmetic is a pointer. As seen in the example above, we do the arithmetic inside the parentheses and then treat the result like it was a declared pointer. In the example above, we dereferenced the result of the addition and it worked.
  • As with all expressions, the above example simply computes where the next integer is located, but does not change the pointer itself.
  • There is no way to derive where a pointer points in the allocated space. We could get the pointer's value, which is an address, but that would not give us much information about which allocation element a pointer points to.

Let's walk through one more example.

In this example, we allocate 100 long integers and initializing each long integer in the space to the value 0 . Then we "rewind" the pointer by subtracting 100*sizeof(long) from it. It is our only way to access all the long integers in the allocated space and we must be careful to work with the pointer so it accurately points to the elements we need.

Pointers and Arrays

We have defined arrays as a collection of elements of the same type, organized in sequence so that we can reference them with an integer index. We have also described memory allocation as a way to create a collection of elements of the same type, placed sequentially in memory. These two ideas are so very close that C treats them the same.

We will demonstrate that pointers are arrays and arrays are pointers.

Pointers and Array References

C allows the same syntax to be used for both arrays and pointers. Let's consider a previous example:

We accessed and assigned values to memory in this way:

We could just as easily have used array reference syntax:

Declaring bigspace as an array also works:

And both methods of accessing the memory space are still equally valid.

Pointers and arrays may be exchanged in assignment statements as well. For example, consider the following:

The first two elements of the array space1 have been initialized to 10 and 20 , respectively. The reverse is true as well:

This illustrates our point: pointers are arrays and arrays are pointers.

Are Pointers and Arrays Really the Same Thing? If pointers are arrays and arrays are pointers, then why are there two different concepts? Pointers and array are not the same thing and are really not treated the same by a C compiler. The point we are making here is that array notation and pointer notation are interchangeable. There are indeed differences between the two structures. The sizeof function will return different values for a pointer (which is a variable that fits into a memory word) and an array (which is a collection of data). A C compiler will treat storage of dynamically allocated memory differently than an array initialized as a string. They have similar uses, but also different uses. So, while it helps to be able to use notation that works for both, arrays and pointers are really different types of data with a variety of different uses.

Pointer Arithmetic and Array Indicies

As we saw in the previous section, pointer arithmetic and using indicies and array notation are interchangeable. We have also seen how to use pointer arithmetic to move pointers through allocated memory space.

As declared and initialized to a memory space, pointers point to the base, the first element, of that space. This is item number 0 in array notation. Whenever we add 1 to a pointer, the system computes the size, in bytes, of the data type that the pointer points to and increments that pointer the number of bytes that make up that data type. Thus, an increment for the pointer is the same as an increment in array notation.

For example, consider this code:

Now, ps points to sa[0] and pl points to sl[0] . Now if we increment both pointers by 1, like this:

ps points to sa[1] and pl points to sl[1] . Even though both pointers were incremented by 1, the addresses were incremented by a different number of bytes.

If we wanted a pointer to start in the middle of an array, instead of the beginning, we would need to use the address of a selected item from that array. For example, if we wanted ps from the example above to point to sa[4] , we would need to derive the address of sa[4] like this:

Now, ps points into the array and not at the beginning.

Pointers and Multidimensional Arrays

Now let's consider how pointers interact with multidimensional arrays. The syntax starts to get a bit clumsy, but if we remember how pointers work with memory, the syntax is easier to understand.

Let's start with two dimensions: rows and columns. Remember that a two-dimensional array is really just a big memory space, organized as rows and columns. If that's true, then a pointer into that space could actually just work as we have described it so far. Here's an example:

This code describes a space comprised of 200 long integers. We could work with ptr as if it was pointing into that 200 long integer space. We could reference ptr[30] or (ptr+30) and it would work, referencing a long integer, 30 items into that space.

However, if we are declaring an array to have two dimensions, then it makes sense to try to use pointers in two dimensions. When we have an array of two dimensions, we can think of it as an "array of arrays". Using one dimension references an entire array from that collection. So referencing table[3] references an entire array at the 4th row of the table.

To use pointers with two dimensions, we need to think like this. If one pointer reference points to an array, then we really need a double reference: one to the the array/row and one more to get the item at the column in the array/row. Consider this type of declaration:

Note the double asterisk: one for rows and one for columns. Now, it would be an error to reference ptr[30] because there are not 30 rows in the table, only 10. In addition, (ptr+5) skips over the first 5 arrays, or 100 long integers, giving us access to the array at table[5] .

The same works to other dimensional arrays. Three dimensions could work like this:

Other dimensions work analogously.

Typed Pointers and Untyped Pointers

We have seen that, in C, pointers can be typed. The data type that a pointer points to informs the compiler on how many bytes to increment a pointer's address when using pointer arithmetic and how to work with pointers in situations where data types matter (like computations or some types of parameters). For example, in this code:

we cannot mix pointers to floats and integers in the same situations we can't mix actual floats and integers. For example:

The last line is an error, because it mixes a floating point number and an integer, producing a floating point number, and tries to assign it to an integer.

There are situations where untyped pointers are appropriate. Untyped pointers are declared to point to a "void" type and may point to values of any type. However, since they have no data type themselves, in order to dereference such a pointer, we must tell the compiler what it points to. Consider this example.

In this code, assume that computeAverage computes the average of the integers in the array and returns that value as a float (we saw this example in Chapter 7). First, note that the pointer p takes an address of an integer variable, then takes the address of a float variable, and that a compiler would think this is correct. Second, in the call to printf , we had to inform the compiler that p was currently pointing to a float variable, and then we could dereference it.

Untyped pointers are also useful as formal parameters to functions. Using a void type for a pointer in a function specification allows flexibility in the actual parameter. Untyped pointers can also be useful as return values; for instance, malloc returns an untyped pointer. We will discuss these ideas further in the next section.

Pointers as Function Parameters

Pointers are the only way parameters can be changed in functions in a way that the caller of the function can access.

We have said in Chapter 6 that functions use pass-by-value for function parameters. In other words, values are copied from actual parameters to formal parameters when the call is made, but not copied back when the function returns. This implies that it is impossible to send changed values back to a function caller.

However, using pointers as parameters to functions makes this type of change possible. If we send a pointer to memory to a function, any changes to the pointer itself will be ignored, but the function can dereference the pointer and make changes to memory that the pointer references. That memory is not part of the parameter list of the function and those changes will be reflected back to the caller.

Let's consider the following example.

Now, because C uses pass-by-value, calling this code like this will not swap anything:

The variables x and y will retain the same values after the function call.

Now, let's change the parameters of swap_integers into pointers. The code would look like this:

Because the parameters are now pointers, we have to dereference them to get at the actual values to be swapped. But now, since we are not changing the parameters, but rather the memory to which they point, memory is changed.

We would call this function this way:

And the values are actually swapped.

Can We Make "swap" Generic with void Pointers? If we can use typed pointers in a swap_integers function, could we use untyped pointers in a generic swap function? That is, by using "void" pointers, could we swap values of any type? The answer, unfortunately, is "NO". While we can certainly specify parameters that are void * parameters, we cannot dereference a void pointer without knowing the data type to which it points. In addition, because we assign a value to temp in the above code, we must know what data types first and second point to, so the compiler knows how to make the assignment.

NULL Pointers

We have stated that pointers contain memory addresses as their values. In addition to addresses, pointers can have a "no address" value, called "null". This null value is actually a special value (many compilers make this value 0, although it could be another special value). Null values are unique; null pointers of any type are guaranteed to be equal.

Null pointers should not be confused with uninitialized pointers. Uninitialized pointers, like uninitialized variables, have no defined value; they occupy space in memory and take on whatever value was left there by the previous variable that occupied that space. Null pointers have a specific null value; uninitialized pointers have an undefined value.

Null pointers typically signify the end of data or an error condition. Dereferencing a null pointer will typically cause a program-crashing error.

Freeing up Memory

Dynamically creating memory with malloc is a great way to only take up the memory that your program needs. Memory on a Pebble smartwatch is limited, and using pointers in this way is frugal.

To continue this frugality, memory space that is allocated by your program must also be deallocated by your program. To deallocate memory that was allocated with malloc , use the free function call. Here's an example of allocating and immediately freeing up memory:

It's as easy as that. It should be done in your program as soon as memory space is not needed.

When freeing memory space, you need to be aware of certain rules:

  • You cannot free memory that was not allocated by malloc . For example, if you assign a pointer the address of a declared variable, freeing that pointer's memory will cause an error. Declared variables are allocated differently than dynamically allocated memory space.
  • You cannot free a null pointer. Null pointers are pointers with "no address" values and freeing them will cause an error.
  • You cannot free uninitialized pointers. These pointers do not point to anything and trying to free them will cause a program error.

Sometimes, memory is allocated by function calls within functions. That kind of allocation is usually freed up by a companion function to the function that allocated the space. (See below in "Pointers and Pebble Programming" for examples.)

How to Avoid Messy Coding with Pointers

Pointers are notorious for creating messy, confusing code. Here are some examples:

These are all equivalent references; they can be used with either int intar[10] or int *intar = malloc(10*sizeof(int)); declarations. Here's another example:

As we will see in the next chapter, strings in C are arrays of characters, ending with a character with a 0 value (a "null" character). Knowing this, the above code will print each character of a string, incrementing to the next character for the next iteration of the loop. Here's one more example:

Running this example will print the value 8 , when the intention is to print the value 10 . The confusion here is the various ways that pointer arithmetic has been done.

Here a few tips to remember to avoid confusion with pointers.

  • Never forget to initialize pointers. This is a simple rule, but it is very confusing when a pointer uses old values.
  • Using array syntax with pointers can be a lot clearer than pointer syntax. This is especially true of multidimensional arrays and array spaces.
  • Be painfully clear when using pointer arithmetic. Using shortcut arithmetic with dereferencing can be very confusing, as we see in the examples above.
  • When using memory allocation, always use the most flexible and meaningful expressions. Calling malloc(16) is not very expressive, but using malloc( 4 * sizeof(int) ) is much more informative.
Pointer Jokes Pointers can be messy and useful. They can also be funny. This link is an xkcd pointer joke. Enjoy!

Pointers and Pebble Programming

Pointers feature prominently in software written for Pebble smartwatches. You have seen this in the many project exercises that have been given in past chapters. For example, every Pebble program needs a window on the screen so that it can interact with the user. This window is declared like this:

and is created like this:

The call to window_create returns a pointer to a Window . This type of allocation is deallocated by a companion to window_create :

Pebble programming uses pointers for most system calls that work with the operating system. Doing so allows these system objects to be allocated in memory and thus hidden from programmers. The fact that they are hidden enhances the abstractness of using them: usually, programmers just care that they work as they are documented and they really don't want to examine every byte of the data used. Using pointers for system calls also allows Pebble to update the system data structures without having to change app source code.

The pattern of allocation, use and deallocation is very common among all system interfaces. The creation/deallocation functions all have different, but similar, names. You should get used to this pattern as you write more Pebble code.

Project Exercises

Project 8.1.

We have said that pointers are arrays and arrays are pointers. In this project exercise, you are asked to prove it! Start with the Bubble Sort in Project 7.1, available at this link , and (1) leave the array declarations alone, but (2) change all the array references to pointer references. You may add any variables you need.

Don't forget the parameters to the sorting functions and the assignment of the number_sorted array from the number array in the handle_init function.

You can find a solution here.

You Cannot Use "void *" Here At first glance, you might think you could make this work with any type by using "void *" to declare the parameters to the sorting functions, like this:

This is fine, but it makes the comparisons in the function code invalid. If the array can be of any type, then how do you know that the < operator works with the specific type that is used at runtime? You could fix the code to use "int *" for comparison like this:

But this code defeats the purpose of using "void *". It says that you can send any type to the sort code, but the code will compare them as integers. And this means we need to be specific about the data type used as function parameters.

Project 8.2

This exercise revisits Project 6.2 again (like we did for Project 7.2). That project, whose answer can be found here , creates an array of strings, which are simply a sequence of characters. These characters are in groups of three, drawing 5 rows of three squares. Note the declaration of the digit_array strings:

So, this collection is a set of 10 pointers to character sequences/arrays. The reference *digit_array[0] will get the first character in the first array, a value of '1' .

In the function draw_digit in the code for Project 7.2, the function receives a sequence of characters in an array. It selects the proper character and renders a square if that character has the value "1".

You are make some changes to draw_digit :

  • Change the parameter digit to a int data type. You will send the function the actual digit to render.
  • Use a char * variable to be assigned an array from the digit_array selection. Use array notation, since it will be simpler.
  • Now use pointer arithmetic to get to the right character inside the nested for loops.
  • Dereference that pointer in the if statement that tests if the choice has the value "1".
  • Finally, change the call to draw_digit to use the choice variable to send the actual digit chosen by the random selection.

You can find an answer to these changes here.

Extra Challenge : For an extra challenge, write draw_digit with no array references at all . The easiest way is to replace the digit_array reference with a reference that selects the character sequence via pointer arithmetic. Nothing else changes! You can find the answer to this challenge at this link.

Project 8.3

Remember Project 5.2? You can find the answer to that project here.

This project asked you to change the colors of pixels by examining each one in a loop and changing the ones that matched a certain color. The main code for this project was a function called replace_colors , whose code is below:

In this code, there was a bitmap that was allocated using a pointer, but referenced using an array. The function set_pixel_color is a good example:

You are to rewrite this code to use pointers to access the bitmap data. To do this you must (1) remove the functions get_pixel_color and set_pixel_color and (2) you must rewrite the nested loops in replace_color to use a single loop and to reference the pixel colors with a pointer.

You can find an answer here.

An Easier Way to Change the Colors in an Image This exercise makes an example of converting array notation into pointer arithmetic. And it show how to directly manipulate image pixel data. However, there is a different, perhaps easier, way to change the image's colors. Instead of changing, say bitmap_data[0] to GColorBlue , we can change the color palette of the image. Image data does not actually reference a color ; each pixel references a palette position, which has a color. If we leave the position reference of the image alone, but change the color at a position in the color, it's faster and simpler. Here is a link to this exercise implemented by changing the color pallete and not the image.

Project 8.4

For Project 8.4, you can get a started with a basic project here.

If you run the initial code, you will see that it's a simple rectangle that bounces around the screen, reminiscent of the bouncing ball from Chapter 3. There is a function, update_block , that computes the position for the image's X and Y coordinates. This function take reference parameters, that are the previous X or Y and the amount to adjust these coodinates. Based on the previous X or Y, the new value is computed.

We want a program that makes the image move randomly when the up button is pressed and in a bouncing manner when the bottom button is pressed. You will need to add code in up_click_handler and down_click_handler to change between the two modes and you will need to add a function, similar to update_block , that randomly assigns new coordinates. Remember to keep the reference parameters. You can check Project 8.2 for how to generate random coordinates.

A completed project can be found here.

results matching " "

No results matching " ".

C Pointers and Memory Allocation

Other resources, declarations, creating a valid pointer value.

int *ip; int x; x = 42; ip = &x;

Using a pointer

printf("%d %d\n", x, *ip);

Memory Allocation and Deallocation

(void *) malloc(size_t numbytes);
int *ip; ip = (int *) malloc(sizeof(int));

Pointers and arrays

int *ip; ip = (int *) malloc( sizeof(int)*10 ); // allocate 10 ints ip[6] = 42; // set the 7th element to 42 ip[10] = 99; // WRONG: array only has 10 elements (this would corrupted memory!)

Freeing memory, and memory leaks

int *ip; ip = (int *) malloc( sizeof(int)*10 ); // allocate 10 ints ... (use the array, etc.) ip = (int *) malloc( sizeof(int)*100 ); // allocate 100 ints ...
int *ip; ip = (int *) malloc( sizeof(int)*10 ); // allocate 10 ints ... (use the array, etc.) free(ip); // de-allocate old array ip = (int *) malloc( sizeof(int)*100 ); // allocate 100 ints ...

Pointers and arrays as arguments

7.0 Pointers

7.1.0 pointer basics.

int i = 5; ip = &i;
ip = &i;
*ip = &i;
int i = 5; int *ip; ip = &i; // Point ip to the memory address of variable i. *ip = 10; // Change the contents of the variable ip points to to 10.

7.2.0 Pointers and Arrays - Pointer Arithmetic

int a[10]; int *pa = &a[0];
int a[10]; int *pa = a;
int a[10]; int *pa = &a[4];
int a[10]; int *pa = a+4; // Converts to &a[0] + 4 or &a[4]
int a[5] = {1,2,3,4,5}; int *pa = a; int i, total = 0; for(i = 0; i
int a[5] = {1,2,3,4,5}; int *pa = a; pa = pa+3; // Increments the pointer by 3 *pa = *pa+3 // WRONG: Increments the contents of the variable // pointed to by pa by 3

7.3.0 Pointers as function arguments

char function(char a[]); char function(char *a);
void function (char a[], int len) { int k; for(k = 0; k

DevsENV

  • C Programming

Pointer in C Programming Language with Practical Examples

  • Conceptual View of a Variable in Memory
  • Declaration of Pointer
  • Initialization of Pointer
  • Dereferencing Pointer
  • Null Pointers
  • Void Pointers
  • Regular Pointers
  • Function Pointers
  • Pointer to Pointer
  • Addition and Subtraction
  • Comparison of Pointers of Same Types
  • More Examples

In C programming, a Pointer variable stores memory address of another variable, pointing to where other variable resides in memory. Pointer variables Provide direct access and manipulation of memory, enhancing code flexibility and efficiency.

¶ Conceptual View of a Variable in Memory

Every variable is assigned a specific memory location, allowing the program to store and retrieve data. This memory can be conceptualized as a contiguous sequence of bytes, each with a unique address. Let’s see how an variable is stored inside memory.

Representation of a Variable in Memory in C programming

Here, an integer variable var stores 13 at memory location 1001 and pointer variable ptr stores the memory location 1001 of var .

Though different data types require different amounts of memory to store a variable, all pointer variables require the same amount of memory for the memory address. The size of a memory address is architecture-dependent, with 64-bit architectures requiring 8 bytes , and 32-bit architectures requiring 4 bytes .

¶ Declaration of Pointer

The declaration of a pointer involves specifying the data type it points to, followed by an asterisk (*) known as dereference operator. This asterisk indicates that the variable is a pointer.

¶ Initialization of Pointer

Pointers can be initialized by assigning the memory address of a variable to them. The address-of operator (&) is used for this purpose.

Here, when we assign &var to a pointer variable ptr it stores the memory address ( 1001 ) of the variable. Now, we can indirectly manipulate data in the address 1001 through ptr .

¶ Dereferencing Pointer

Dereferencing a pointer is accomplished using the dereference operator *. This operator, when applied to a pointer, retrieves the value stored at the memory address pointed to by that pointer.

When we print value in ptr it prints a memory location in hexadecimal as it stores a memory location. But when we dereference it with * it prints the value in the memory location stored in it.

¶ Types of Pointers in C Programming

Depending on the types of data that pointer variables point to, they are mainly classified as follows,

¶ Null Pointers

A null pointer is a pointer that does not point to any memory location. It is often used to indicate the absence of a valid memory address. In C, a null pointer is represented by assigning the value NULL to a pointer.

¶ Void Pointers

Void pointers, or generic pointers, are pointers that can point to objects of any data type. They can be casted to different types according to need. Thus, providing a way to achieve flexibility in handling different data types without explicitly specifying the type. But they can not be dereferenced.

¶ Regular Pointers

They are the pointers that point to specific data types like int, char, or float. These pointers are essential for efficiently manipulating and accessing individual elements of basic data types. Examples we have seen so far are mostly of this type.

¶ Function Pointers

Function pointers point to functions instead of data. They are particularly useful in scenarios where different functions need to be called based on certain conditions. They actually point to the code segment in the memory of the function it is pointing to, allowing the execution of the function through the pointer.

¶ Pointer to Pointer

A pointer to a pointer, also known as a multilevel pointer, stores the address of another pointer. This type of pointer is especially useful in dynamic memory allocation and multidimensional arrays.

¶ Pointer Arithmetic

Pointer arithmetic is different from other variables. Pointer arithmetic supports following operations,

¶ Addition and Subtraction

Adding or subtracting an integer value to a pointer results in moving in memory by a distance calculated based on the size of the data type the pointer points to. For integers, pointers move 4 bytes.

¶ Comparison of Pointers of Same Types

We cam compare two pointers of the same type using relational operators. When comparing pointers, you are comparing the memory addresses they hold.

¶ More Examples

  • Print an Array Using Pointer
  • Swap Two Numbers using Pointers

All Tutorials in this playlist

What is C Programming and How to Start C Programming

What is C Programming and How to Start C Programming

Getting Started Your First Coding With C Programming

Getting Started Your First Coding With C Programming

Variable and Data Types with Practical Examples in C Programming

Variable and Data Types with Practical Examples in C Programming

Input and Output in C Programming

Input and Output in C Programming

Conditional in C Programming - if-else, elseif, switch-case

Conditional in C Programming - if-else, elseif, switch-case

Loops in C Programming - for loop, while loop and do-while loop

Loops in C Programming - for loop, while loop and do-while loop

Functions in C Programming - with Practical examples

Functions in C Programming - with Practical examples

Arrays in C Programming - Algorithm and Practical examples

Arrays in C Programming - Algorithm and Practical examples

Recursion in C Programming Language with Practical Examples

Recursion in C Programming Language with Practical Examples

Structure in C Programming Language with practical examples

Structure in C Programming Language with practical examples

File Handling in C Programming Language with Practical Examples

File Handling in C Programming Language with Practical Examples

Pointer in C Programming Language with Practical Examples

Student Management Complete Application Using C Programming

C Project - Complete Calculator Application using C Programming

C Project - Complete Calculator Application using C Programming

Popular tutorials, vue js 3 - complete advance crud example with vuex, vue-validate, pagination, searching and everything, laravel eloquent vs db query builder [performance and other statistics], laravel role permission management system full example with source code, start wordpress plugin development with react js easily in just few steps, laravel membership management full project demo with source codes, numerical methods for engineers ebook & solution download - download pdf, connect your react app with websocket to get real time data, #ajax with laravel api and more - learn laravel beyond the limit, laravel ecommerce complete web application with admin panel, what is seeder in laravel and why we need it.

  • Artificial Intelligence (AI)
  • Bash Scripting

Bootstrap CSS

  • Code Editor
  • Computer Engineering
  • Data Structure and Algorithm

Design Pattern in PHP

Design Patterns - Clean Code

  • Git Commands

Interview Prepration

Java Programming

Laravel PHP Framework

Online Business

  • Programming

React Native

Rust Programming

Tailwind CSS

Uncategorized

Windows Operating system

  • Woocommerce

WordPress Development

  • C-sharp programming
  • Design pattern
  • Mathematics
  • Rust Programming Language
  • Windows terminal
  • WordPress Plugin Development

C Functions

C structures, c memory address, memory address.

When a variable is created in C, a memory address is assigned to the variable.

The memory address is the location of where the variable is stored on the computer.

When we assign a value to the variable, it is stored in this memory address.

To access it, use the reference operator ( & ), and the result represents where the variable is stored:

Note: The memory address is in hexadecimal form (0x..). You will probably not get the same result in your program, as this depends on where the variable is stored on your computer.

You should also note that &myAge is often called a "pointer". A pointer basically stores the memory address of a variable as its value. To print pointer values, we use the %p format specifier.

You will learn much more about pointers in the next chapter.

Why is it useful to know the memory address?

Pointers 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 .

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

Get Certified

COLOR PICKER

colorpicker

Report Error

If you want to report an error, or if you want to make a suggestion, do not hesitate to send us an e-mail:

[email protected]

Top Tutorials

Top references, top examples, get certified.

A guide to pointers in C

A guide to pointers in C

Everything you need to know about pointers.

Vishesh Raghuvanshi's photo

Table of contents

Address of a variable, pointer operators, format specifiers for pointers, size of pointer variable.

Every variable in C has a memory location where it is stored. This memory location is called the variable's address.

Print the memory address of a variable in Go (Golang)

A pointer is a variable that stores the address of another variable.

We use the * (asterisk) operator to define pointers and the & (address of) operator to get the address of a variable.

For example:

Here p is a pointer that stores the address of a .

We use the -> operator to access the value at the address stored in the pointer.

Pointers allow us to pass variables by reference instead of by value. This is useful to modify the original variable.

Here are short notes on the main pointer operators in C:

& - Address Of Operator

Returns the memory address of a variable.

Syntax: &variable_name

* Dereference Operator

Accesses the value at the address stored in a pointer.

Syntax: *pointer_name

-> - Structure Dereference Operator

Accesses a member of a structure through a pointer.

Equivalent to using the . operator, but dereferences the pointer first.

The format specifiers for pointers in C are:

%p - To print a generic pointer address. This is the preferred way.

%#x - To print a pointer address with 0x prefix.

%x - To print a pointer address as an unsigned hexadecimal integer, without the 0x prefix.

%d would give an incorrect result when used to print a pointer address. It may print some decimal number, but that number does not represent the actual pointer address.

0x7fff17337f4c

The size of a pointer variable depends on the system architecture. It can be 4 bytes or 8 bytes, depending on whether it is a 32-bit or 64-bit system.

On 32-bit systems, pointers are usually 4 bytes in size

On 64-bit systems, pointers are usually 8 bytes in size

The size of a pointer variable does not depend on the type of data it is pointing to. A pointer to an int and a pointer to a char will have the same size, depending on the system architecture.

Did you find this article valuable?

Support Vishesh Raghuvanshi by becoming a sponsor. Any amount is appreciated!

assign pointer to memory address in c

Advertisement

The Basics of C Programming

  • Share Content on Facebook
  • Share Content on LinkedIn
  • Share Content on Flipboard
  • Share Content on Reddit
  • Share Content via Email

Pointers: Understanding Memory Addresses

assign pointer to memory address in c

The previous discussion becomes a little clearer if you understand how memory addresses work in a computer's hardware. If you have not read it already, now would be a good time to read How Bits and Bytes Work to fully understand bits, bytes and words.

All computers have memory , also known as RAM ( random access memory ). For example, your computer might have 16 or 32 or 64 megabytes of RAM installed right now. RAM holds the programs that your computer is currently running along with the data they are currently manipulating (their variables and data structures). Memory can be thought of simply as an array of bytes. In this array, every memory location has its own address -- the address of the first byte is 0, followed by 1, 2, 3, and so on. Memory addresses act just like the indexes of a normal array. The computer can access any address in memory at any time (hence the name "random access memory"). It can also group bytes together as it needs to to form larger variables, arrays, and structures. For example, a floating point variable consumes 4 contiguous bytes in memory. You might make the following global declaration in a program:

This statement says, "Declare a location named f that can hold one floating point value." When the program runs, the computer reserves space for the variable f somewhere in memory. That location has a fixed address in the memory space, like this:

While you think of the variable f , the computer thinks of a specific address in memory (for example, 248,440). Therefore, when you create a statement like this:

The compiler might translate that into, "Load the value 3.14 into memory location 248,440." The computer is always thinking of memory in terms of addresses and values at those addresses.

There are, by the way, several interesting side effects to the way your computer treats memory. For example, say that you include the following code in one of your programs:

The output that you see from the program will probably look like this:

Why are t[0] and u incorrect? If you look carefully at the code, you can see that the for loops are writing one element past the end of each array. In memory, the arrays are placed adjacent to one another, as shown here:

assign pointer to memory address in c

Therefore, when you try to write to s[4], which does not exist, the system writes into t[0] instead because t[0] is where s[4] ought to be. When you write into t[4], you are really writing into u. As far as the computer is concerned, s[4] is simply an address, and it can write into it. As you can see however, even though the computer executes the program, it is not correct or valid. The program corrupts the array t in the process of running. If you execute the following statement, more severe consequences result:

The location s[1000000] is more than likely outside of your program's memory space. In other words, you are writing into memory that your program does not own. On a system with protected memory spaces (UNIX, Windows 98/NT), this sort of statement will cause the system to terminate execution of the program. On other systems (Windows 3.1, the Mac), however, the system is not aware of what you are doing. You end up damaging the code or variables in another application. The effect of the violation can range from nothing at all to a complete system crash. In memory, i, s, t and u are all placed next to one another at specific addresses. Therefore, if you write past the boundaries of a variable, the computer will do what you say but it will end up corrupting another memory location.

Because C and C++ do not perform any sort of range checking when you access an element of an array, it is essential that you, as a programmer, pay careful attention to array ranges yourself and keep within the array's appropriate boundaries. Unintentionally reading or writing outside of array boundaries always leads to faulty program behavior.

As another example, try the following:

This code tells the compiler to print out the address held in p , along with the address of i. The variable p starts off with some crazy value or with 0. The address of i is generally a large value. For example, when I ran this code, I received the following output:

which means that the address of i is 2147478276. Once the statement p = &i; has been executed, p contains the address of i . Try this as well:

This code tells the compiler to print the value that p points to. However, p has not been initialized yet; it contains the address 0 or some random address. In most cases, a segmentation fault (or some other run-time error) results, which means that you have used a pointer that points to an invalid area of memory. Almost always, an uninitialized pointer or a bad pointer address is the cause of segmentation faults.

Having said all of this, we can now look at pointers in a whole new light. Take this program, for example:

Here is what's happening:

assign pointer to memory address in c

The variable i consumes 4 bytes of memory. The pointer p also consumes 4 bytes (on most machines in use today, a pointer consumes 4 bytes of memory. Memory addresses are 32-bits long on most CPUs today, although there is a increasing trend toward 64-bit addressing). The location of i has a specific address, in this case 248,440. The pointer p holds that address once you say p = &i; . The variables *p and i are therefore equivalent.

The pointer p literally holds the address of i . When you say something like this in a program:

what comes out is the actual address of the variable i .

Please copy/paste the following text to properly cite this HowStuffWorks.com article:

Exploring C – How to Print the Address of a Pointer (Step-by-Step Guide)

Understanding pointers in c.

Before we dive into the process of printing the address of a pointer in C, let’s take a moment to understand what pointers are and why they are important in the first place.

assign pointer to memory address in c

In C, a pointer is a variable that stores the memory address of another variable. This allows us to indirectly access and manipulate the value of the variable by utilizing its memory address.

Variables in C are stored in specific memory locations, and each location has a unique address. By using pointers, we can reference these memory addresses directly, allowing for more efficient memory management and the ability to work with complex data structures.

To better comprehend pointers, it’s crucial to grasp the concept of memory addresses. In C, every variable is allocated a unique memory address, which can be thought of as the physical location where the variable’s value is stored.

Now that we have a basic understanding of pointers and memory addresses, let’s explore how to properly declare and initialize pointers in C.

Accessing the Address of a Pointer

The process of accessing and printing the address of a pointer in C is relatively straightforward. To achieve this, we utilize the ‘&’ operator, also known as the “address-of” operator.

The ‘&’ operator is used to retrieve the memory address of a variable or a pointer. It is placed in front of the variable or pointer that you want to obtain the address of.

Let’s take a look at a simple code example that demonstrates how to print the address of a pointer:

Here, we declare an integer variable ‘num’ and assign it a value of 10. Then, we create a pointer ‘ptr’ and initialize it with the address of ‘num’ using the ‘&’ operator.

Finally, we use the ‘printf’ function to print the address of the pointer. Note that we cast the pointer to ‘void*’ to ensure proper formatting when printing.

Implementing the Step-by-Step Guide

Now that we’ve covered the basic concepts, let’s walk through a step-by-step guide on how to print the address of a pointer in C.

Step 1: Declare and initialize a pointer variable

The first step is to declare and initialize a pointer variable. This involves both declaring the pointer and assigning it a valid memory address.

Take a look at the following example:

Here, we declare an integer variable ‘num’ and assign it a value of 20. Then, we create a pointer ‘ptr’ and initialize it with the address of ‘num’ using the ‘&’ operator.

Step 2: Print the address of the pointer

Once we have initialized the pointer, the next step is to print its address. By using the ‘&’ operator again, we can retrieve the memory address of the pointer itself.

Consider the following example:

In this code snippet, we use the ‘printf’ function to print the address of the pointer ‘ptr’. Note that once again, we cast the pointer to ‘void*’ to ensure correct formatting.

Step 3: Test the code

After implementing the above steps, it’s important to test our code to ensure that it functions correctly.

Running the code example from Step 2 should result in the following output:

The value displayed might differ depending on the system and compiler being used. However, the output will consistently represent the memory address of the pointer.

In this blog post, we have explored the process of printing the address of a pointer in C. By understanding the concept of pointers and memory addresses, we can manipulate memory more efficiently and work with complex data structures.

Remember, to print the address of a pointer, we use the ‘&’ operator, and to ensure proper formatting, we cast the pointer to ‘void*’ before printing it using ‘printf’.

By following the step-by-step guide outlined in this post, beginners in C programming can gain a solid understanding of how to print the address of a pointer and apply this knowledge to their own projects.

So go ahead, practice printing the address of pointers in C, and unleash the full potential of your programming skills!

Related posts:

  • Mastering Pointers in C – A Comprehensive Guide for Beginners
  • C Print Pointer – A Comprehensive Guide to Printing Pointers in the C Programming Language
  • The Ultimate Guide to Print Pointer in C – Everything You Need to Know
  • Mastering the Array of Pointers in C – A Comprehensive Guide
  • Unveiling the Mystery – What Does PTR Mean? A Comprehensive Explanation

C Data Types

C operators.

  • C Input and Output
  • C Control Flow
  • C Functions
  • C Preprocessors

C File Handling

  • C Cheatsheet

C Interview Questions

  • C Programming Language Tutorial
  • C Language Introduction
  • Features of C Programming Language
  • C Programming Language Standard
  • C Hello World Program
  • Compiling a C Program: Behind the Scenes
  • Tokens in C
  • Keywords in C

C Variables and Constants

  • C Variables
  • Constants in C
  • Const Qualifier in C
  • Different ways to declare variable as constant in C
  • Scope rules in C
  • Internal Linkage and External Linkage in C
  • Global Variables in C
  • Data Types in C
  • Literals in C
  • Escape Sequence in C
  • Integer Promotions in C
  • Character Arithmetic in C
  • Type Conversion in C

C Input/Output

  • Basic Input and Output in C
  • Format Specifiers in C
  • printf in C
  • Scansets in C
  • Formatted and Unformatted Input/Output functions in C with Examples
  • Operators in C
  • Arithmetic Operators in C
  • Unary operators in C
  • Relational Operators in C
  • Bitwise Operators in C
  • C Logical Operators
  • Assignment Operators in C
  • Increment and Decrement Operators in C
  • Conditional or Ternary Operator (?:) in C
  • sizeof operator in C
  • Operator Precedence and Associativity in C

C Control Statements Decision-Making

  • Decision Making in C (if , if..else, Nested if, if-else-if )
  • C - if Statement
  • C if...else Statement
  • C if else if ladder
  • Switch Statement in C
  • Using Range in switch Case in C
  • while loop in C
  • do...while Loop in C
  • For Versus While
  • Continue Statement in C
  • Break Statement in C
  • goto Statement in C
  • User-Defined Function in C
  • Parameter Passing Techniques in C
  • Function Prototype in C
  • How can I return multiple values from a function?
  • main Function in C
  • Implicit return type int in C
  • Callbacks in C
  • Nested functions in C
  • Variadic functions in C
  • _Noreturn function specifier in C
  • Predefined Identifier __func__ in C
  • C Library math.h Functions

C Arrays & Strings

  • Properties of Array in C
  • Multidimensional Arrays in C
  • Initialization of Multidimensional Array in C
  • Pass Array to Functions in C
  • How to pass a 2D array as a parameter in C?
  • What are the data types for which it is not possible to create an array?
  • How to pass an array by value in C ?
  • Strings in C
  • Array of Strings in C
  • What is the difference between single quoted and double quoted declaration of char array?
  • C String Functions
  • Pointer Arithmetics in C with Examples
  • C - Pointer to Pointer (Double Pointer)
  • 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
  • Dangling, Void , Null and Wild Pointers in C
  • Near, Far and Huge Pointers in C
  • restrict keyword in C

C User-Defined Data Types

  • C Structures
  • dot (.) Operator in C
  • Structure Member Alignment, Padding and Data Packing
  • Flexible Array Members in a structure in C
  • Bit Fields in C
  • Difference Between Structure and Union in C
  • Anonymous Union and Structure in C
  • Enumeration (or enum) in C

C Storage Classes

  • Storage Classes in C
  • extern Keyword in C
  • Static Variables in C
  • Initialization of static variables in C
  • Static functions in C
  • Understanding "volatile" qualifier in C | Set 2 (Examples)
  • Understanding "register" keyword in C

C Memory Management

  • Memory Layout of C Programs

Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc()

  • Difference Between malloc() and calloc() with Examples
  • What is Memory Leak? How can we avoid?
  • Dynamic Array in C
  • How to dynamically allocate a 2D array in C?
  • Dynamically Growing Array in C

C Preprocessor

  • C Preprocessor Directives
  • How a Preprocessor works in C?
  • Header Files in C
  • What’s difference between header files "stdio.h" and "stdlib.h" ?
  • How to write your own header file in C?
  • Macros and its types in C
  • Interesting Facts about Macros and Preprocessors in C
  • # and ## Operators in C
  • How to print a variable name in C?
  • Multiline macros in C
  • Variable length arguments for Macros
  • Branch prediction macros in GCC
  • typedef versus #define in C
  • Difference between #define and const in C?
  • Basics of File Handling in C
  • C fopen() function with Examples
  • EOF, getc() and feof() in C
  • fgets() and gets() in C language
  • fseek() vs rewind() in C
  • What is return type of getchar(), fgetc() and getc() ?
  • Read/Write Structure From/to a File in C
  • C Program to print contents of file
  • C program to delete a file
  • C Program to merge contents of two files into a third file
  • What is the difference between printf, sprintf and fprintf?
  • Difference between getc(), getchar(), getch() and getche()

Miscellaneous

  • time.h header file in C with Examples
  • Input-output system calls in C | Create, Open, Close, Read, Write
  • Signals in C language
  • Program error signals
  • Socket Programming in C
  • _Generics Keyword in C
  • Multithreading in C
  • C Programming Interview Questions (2024)
  • Commonly Asked C Programming Interview Questions | Set 1
  • Commonly Asked C Programming Interview Questions | Set 2
  • Commonly Asked C Programming Interview Questions | Set 3

Since C is a structured language, it has some fixed rules for programming. One of them includes changing the size of an array. An array is a collection of items stored at contiguous memory locations. 

arrays

As can be seen, the length (size) of the array above is 9. But what if there is a requirement to change this length (size)? For example, 

  • If there is a situation where only 5 elements are needed to be entered in this array. In this case, the remaining 4 indices are just wasting memory in this array. So there is a requirement to lessen the length (size) of the array from 9 to 5.
  • Take another situation. In this, there is an array of 9 elements with all 9 indices filled. But there is a need to enter 3 more elements in this array. In this case, 3 indices more are required. So the length (size) of the array needs to be changed from 9 to 12.

This procedure is referred to as Dynamic Memory Allocation in C . Therefore, C Dynamic Memory Allocation can be defined as a procedure in which the size of a data structure (like Array) is changed during the runtime. C provides some functions to achieve these tasks. There are 4 library functions provided by C defined under <stdlib.h> header file to facilitate dynamic memory allocation in C programming. They are: 

Let’s look at each of them in greater detail.

C malloc() method

The “malloc” or “memory allocation” method in C is used to dynamically allocate a single large block of memory with the specified size. It returns a pointer of type void which can be cast into a pointer of any form. It doesn’t Initialize memory at execution time so that it has initialized each block with the default garbage value initially. 

Syntax of malloc() in C

ptr = (int*) malloc(100 * sizeof(int)); Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the pointer ptr holds the address of the first byte in the allocated memory.  

assign pointer to memory address in c

If space is insufficient, allocation fails and returns a NULL pointer.

Example of malloc() in C

C calloc() method.

  • “calloc” or “contiguous allocation” method in C is used to dynamically allocate the specified number of blocks of memory of the specified type. it is very much similar to malloc() but has two different points and these are:
  • It initializes each block with a default value ‘0’.
  • It has two parameters or arguments as compare to malloc().

Syntax of calloc() in C

For Example:  

ptr = (float*) calloc(25, sizeof(float)); This statement allocates contiguous space in memory for 25 elements each with the size of the float.  

assign pointer to memory address in c

Example of calloc() in C

C free() method.

“free” method in C is used to dynamically de-allocate the memory. The memory allocated using functions malloc() and calloc() is not de-allocated on their own. Hence the free() method is used, whenever the dynamic memory allocation takes place. It helps to reduce wastage of memory by freeing it.

Syntax of free() in C

assign pointer to memory address in c

Example of free() in C

C realloc() method.

“realloc” or “re-allocation” method in C is used to dynamically change the memory allocation of a previously allocated memory. In other words, if the memory previously allocated with the help of malloc or calloc is insufficient, realloc can be used to dynamically re-allocate memory . re-allocation of memory maintains the already present value and new blocks will be initialized with the default garbage value.

Syntax of realloc() in C

assign pointer to memory address in c

Example of realloc() in C

One another example for realloc() method is:

assign pointer to memory address in c

Please Login to comment...

Similar reads.

  • Dynamic Memory Allocation
  • What are Tiktok AI Avatars?
  • Poe Introduces A Price-per-message Revenue Model For AI Bot Creators
  • Truecaller For Web Now Available For Android Users In India
  • Google Introduces New AI-powered Vids App
  • 30 OOPs Interview Questions and Answers (2024)

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

MarketSplash

What Is Pointers In C++ And How To Use It

Navigating memory management is a fundamental aspect of C++ programming, and pointers are at the core of this. In this article, we’ll explore the mechanics and usage of pointers in C++, from basic pointer operations to smart pointers, diving into real code examples to cement your understanding.

💡 KEY INSIGHTS

  • Understanding Smart Pointers is essential in modern C++ development, as they provide automatic memory management and prevent common pitfalls like memory leaks and dangling pointers.
  • The RAII (Resource Acquisition Is Initialization) principle is a powerful technique in C++ that simplifies resource management, ensuring timely cleanup and preventing resource leaks.
  • Shared Pointers facilitate efficient memory sharing among multiple objects, reducing memory overhead and enhancing program performance when dealing with shared data structures.
  • Leveraging Unique Pointers can enforce exclusive ownership of resources, preventing accidental resource duplication and ensuring safer and more robust code in C++ applications.

Pointers in C++ are a fundamental concept that can significantly enhance your coding capabilities. They allow for direct memory manipulation, making your programs more efficient and opening doors to advanced programming techniques. While pointers can seem complex at first, a clear understanding of how they work will become an invaluable tool in your programming toolbox.

assign pointer to memory address in c

What Is Pointers In C++

Declaring and initializing pointers, pointer arithmetic and operations, pointers and arrays, pointers to functions, memory management with pointers, pointers and classes, common pointer mistakes and how to avoid them, smart pointers in c++, frequently asked questions, pointer initialization, syntax and indirection, pointers and function arguments.

A pointer in C++ is a variable that stores a memory address, serving as a direct link to the value stored at that location. It functions as a gateway, allowing us to read and write to the memory locations it points to.

When declaring a pointer, it’s essential to initialize it , either to another pointer or to nullptr . This ensures it doesn't point to an arbitrary memory location, potentially leading to undefined behavior.

The * symbol serves a dual role; in declarations, it specifies a type is a pointer. When used in expressions, it acts as the dereference operator and accesses the value pointed to.

Pointers are often used as function arguments to allow functions to modify variables from the calling function. This is commonly termed as passing by reference .

Using pointers effectively can make your code more flexible and efficient. However, it is crucial to manage the memory pointers are associated with responsibly to avoid errors and undefined behavior.

Initializing Pointers

Pointer assignment.

To start working with pointers in C++, you first need to declare a pointer variable. This involves specifying the data type that the pointer is going to point to, followed by the asterisk symbol (*) before the pointer name.

Here, we have declared a pointer named 'ptr' that is intended to point to an integer. The data type of 'ptr' is "pointer to int".

After declaration, it’s important to initialize the pointer, either with the address of a variable or with the NULL value. Uninitialized pointers can lead to undefined behavior.

In this example, 'ptr' is a pointer that holds the address of the variable 'num'. The ampersand (&) is used to get the address of 'num'.

Alternatively, pointers can be initialized to NULL , which means they are pointing to no location. This is often a good practice, as it makes it clear that the pointer is not yet pointing to a valid location.

Initializing to 'NULL' is a way to signify that the pointer 'ptr' is not pointing to any memory location initially. In C++11 and later, you can also use 'nullptr' instead of 'NULL'.

Pointers can also be assigned to hold the address of a variable of the appropriate type at any time after their declaration.

Here, 'ptr' is assigned the address of 'num' after its declaration. Again, the ampersand (&) symbol is used to obtain the address of 'num'.

In C++, pointers can be manipulated using a set of specific arithmetic operations, often referred to as pointer arithmetic . These operations enable you to navigate through memory, making pointers a powerful tool for array manipulation and data handling.

Basic Pointer Operations

Subtracting pointers, comparing pointers.

The basic arithmetic operations for pointers include increment ( ++ ), decrement ( -- ), addition ( + ), and subtraction ( - ).

In this example, 'ptr' initially points to the first element of 'arr'. After the increments, it points to the third element (which holds the value '40').

You can subtract two pointers of the same type to find the offset between them. This is useful when you need to calculate the distance between two elements in an array.

Here, 'distance' will hold the value '4', which represents the number of elements between 'start' and 'end'.

Pointers can also be compared using relational operators ( < , > , == , != , <= , >= ). This is useful for checking the positions of two pointers relative to each other.

This condition checks whether 'ptr1' and 'ptr2' are pointing to the same memory location.

It is important to remember that pointer arithmetic is only valid among pointers that point to elements of the same array , or one past the last element of that array. Attempting to perform arithmetic with pointers that don't satisfy this can lead to undefined behavior.

Accessing Array Elements With Pointers

Using pointers to traverse arrays, pointer arithmetic vs array indexing, pointers and multidimensional arrays.

In C++, arrays and pointers are closely related. An array name essentially acts as a constant pointer to the first element of the array. This relationship is fundamental in understanding how to navigate arrays using pointers.

Instead of using array indices, you can use pointer arithmetic to access elements of an array. Incrementing a pointer moves it to the next array element, while decrementing moves it to the previous element.

After this sequence of operations, 'ptr' points to the fourth element of 'arr', which is '4'.

You can use pointers to loop through an array, similar to how you would use an index with a traditional loop.

This loop uses 'ptr' to traverse the array. The loop prints each element of 'arr', outputting "1 2 3 4 5".

While array indexing is more common and usually more readable, pointer arithmetic can be more efficient because it often involves fewer machine instructions.

Both of these lines set the variable (value1 or value2) to the fourth element of 'arr'. They are equivalent operations.

For multidimensional arrays , pointers can also be used to navigate through the elements. In a 2D array, for example, you need a pointer to a pointer to traverse the array.

Here, 'ptr' is a pointer to an array of 3 integers. It points to the first "row" of 'arr'. You can move it to the next row with 'ptr++'.

It is important to use pointers correctly when working with arrays, ensuring you stay within the bounds of the array, to avoid undefined behavior and potential program crashes.

assign pointer to memory address in c

More about arrays

Declaring Pointers To Functions

Assigning a function to a pointer, calling a function through a pointer, using function pointers as parameters.

In C++, you can have pointers to functions , allowing functions to be passed as parameters to other functions, stored in data structures, and returned from other functions, much like other data types. This enables a high degree of code reusability and can be used to implement callback functions, table of functions, and more.

To declare a pointer to a function , you need to specify the function’s return type, followed by an asterisk, and then the name of the pointer variable, along with the parameter types of the function.

Here, 'functionPtr' is a pointer to a function that takes an integer and a double as parameters and returns no value (void).

To assign a function to a function pointer , you simply use the name of the function without parentheses.

'exampleFunction' is assigned to the function pointer 'functionPtr'. Note that we are not calling 'exampleFunction'; we are just assigning its address to 'functionPtr'.

Once a function is assigned to a pointer, you can call the function using the pointer in the same way you would call the function directly.

This line of code calls 'exampleFunction' through the 'functionPtr' with arguments '5' and '3.14'. It’s equivalent to calling 'exampleFunction(5, 3.14);' directly.

images

“Learning to write programs stretches your mind, and helps you think better, creates a way of thinking about things that I think is helpful in all domains.

Source: Udacity

Function pointers can also be passed as parameters to other functions , enabling callbacks and higher-order functions.

In this example, 'applyFunction' is a function that takes two parameters, as well as a function pointer 'func'. It calls the function pointed to by 'func' with the provided parameters.

Using pointers to functions can make your code more modular and enable you to use functions as first-class citizens, similar to objects and basic types, thereby facilitating more dynamic and flexible programming designs.

In C++, pointers play a crucial role in memory management . They allow you to have direct control over memory allocation and deallocation. This low-level control is a double-edged sword: it can lead to efficient use of memory, but also to issues like memory leaks and undefined behavior if not used carefully.

Here, 'ptr' is a pointer to an int allocated on the heap. We then store the value '42' in this memory location.

After calling delete , the memory is freed, and 'ptr' should be set to nullptr to avoid undefined behavior.

This code snippet creates a dynamic array of '5' integers and then deallocates the memory.

In this code, if the allocation of a large block of memory fails, a std::bad_alloc exception is caught and an error message is printed.

Here, 'smartPtr' is a std::unique_ptr that takes ownership of a dynamically allocated int . When 'smartPtr' goes out of scope, it automatically deletes the managed memory.

Using smart pointers is a modern and safer approach to memory management in C++, as they help in reducing the risk of memory leaks by ensuring that memory is deallocated when it is no longer needed.

In C++, pointers can be used with classes to create dynamic instances of classes, to implement polymorphic behavior, and to optimize performance by avoiding unnecessary copying of objects. Working with pointers to classes is a fundamental concept, especially when designing complex data structures and systems.

Creating Dynamic Objects

Accessing members via pointers, deleting dynamic objects, pointers and polymorphism, smart pointers and classes.

Using the new operator , you can allocate memory for an instance of a class on the heap, which returns a pointer to the object .

Here, 'objPtr' is a pointer to an object of 'MyClass'. This object is dynamically allocated and initialized with '5'.

To access class members via a pointer to a class object , the arrow operator -> is used.

In this example, we are accessing the 'x' member of the 'MyClass' object pointed to by 'objPtr' and setting it to '10'.

When a class object is created dynamically, it is crucial to release the allocated memory using the delete operator .

After this, the memory used by the object is released, and 'objPtr' is set to nullptr to avoid a dangling pointer.

One of the powerful uses of pointers in C++ is to achieve polymorphism . Using base class pointers , you can point to objects of derived classes.

In this example, 'bPtr' is a pointer of type 'Base', but it is pointing to an object of type 'Derived'. The show function of 'Derived' class is called, demonstrating polymorphism.

Smart pointers , like std::unique_ptr and std::shared_ptr , can also be used with class objects to manage their lifetimes automatically.

Here, 'smartObjPtr' is a std::unique_ptr that takes ownership of a dynamically allocated 'MyClass' object. When 'smartObjPtr' goes out of scope, it automatically deletes the managed object.

Using pointers in conjunction with classes enables advanced programming techniques like polymorphism and dynamic object creation, which are central in object-oriented programming in C++.

Uninitialized pointers can point to random memory locations. Always initialize pointers, either to a valid address or to nullptr .

In the code above, 'p' is an uninitialized pointer, and dereferencing it results in undefined behavior. Initialize 'p' to nullptr or a valid address to avoid this.

In this example, we first check if 'ptr' is not nullptr before attempting to dereference it. This avoids null pointer dereferencing.

Above, we allocate an array of integers dynamically and later release the memory using delete[] . Failing to delete 'arr' would result in a memory leak.

Here, after deleting 'p', we set it to `nullptr'. This avoids a dangling pointer, as 'p' no longer points to an undefined memory location.

In this code, 'ptr' moves outside of 'arr', which is dangerous. Always ensure that pointer arithmetic stays within array bounds.

In this example, 'x' is deleted twice, which is not allowed. Ensure that each new operation has exactly one corresponding delete operation.

assign pointer to memory address in c

Common pointer mistakes can lead to serious bugs. Being mindful of these issues and adopting good practices, such as using smart pointers and consistently checking for nullptr before dereferencing, can significantly reduce these risks.

Smart pointers are a modern C++ feature that manage the memory of their underlying objects, helping to avoid common memory management errors. They automatically release memory when no longer needed.

Here, unique_ptr takes ownership of a dynamically allocated int , while shared_ptr is initialized using make_shared . Memory is automatically released when these pointers go out of scope.

std::unique_ptr is a unique pointer that takes ownership of a dynamically allocated object. When the unique_ptr goes out of scope, it deletes its underlying object .

The unique_ptr 'uptr' owns its int object and cannot be copied. When 'uptr' goes out of scope, the memory is released automatically.

std::shared_ptr is a shared pointer that allows multiple shared_ptr instances to share ownership of an object. The object is deleted when the last owning shared_ptr is destroyed .

Here, 'sptr1' and 'sptr2' share ownership of an int . The int is deleted only after both 'sptr1' and 'sptr2' are destroyed.

std::weak_ptr is a weak pointer that observes an object owned by shared_ptr , but doesn't prevent its destruction. It’s useful to break circular references between shared_ptr instances.

Here, 'wk_ptr' is a weak_ptr observing an int owned by 'sh_ptr'. It does not extend the lifetime of the int object.

You can convert a weak_ptr to a shared_ptr to temporarily gain shared ownership of the object.

In this code, 'wk_ptr.lock()' creates a shared_ptr (here 'temp_sptr') from 'wk_ptr'. It’s essential to check for nullptr before using 'temp_sptr' to ensure the object is still alive.

How Do Smart Pointers Avoid Memory Leaks?

Smart pointers automatically delete their underlying objects when those objects are no longer needed. This ensures that the memory occupied by these objects is released, effectively preventing memory leaks that can occur due to manual memory management.

When Should I Use std::unique_ptr ?

Use std::unique_ptr when you want a single owner for a dynamically allocated object. It’s perfect when you want to ensure that only one pointer has the responsibility to delete the object it points to, which happens automatically when the std::unique_ptr goes out of scope.

Can I Copy a std::unique_ptr ?

No, std::unique_ptr instances cannot be copied, because they are designed to have sole ownership of their managed object. However, you can move a std::unique_ptr , transferring ownership from one to another.

When Should I Use std::shared_ptr ?

Use std::shared_ptr when you want multiple pointers to share ownership of a dynamically allocated object. When the last shared_ptr that owns the object is destroyed or reset, the object is automatically deleted.

When and Why Should I Use std::weak_ptr ?

Use std::weak_ptr when you want to observe an object owned by a shared_ptr , but you don’t want to extend the object’s lifetime. This is useful for avoiding circular references that can lead to memory leaks with shared_ptr .

Let’s test your knowledge!

Which of the following is used to declare a pointer in C++?

Continue Learning With These C++ Guides

  • C++ Setlist: What It Is And How To Use It
  • What Is C++ Iterators And How To Use It
  • C++ Deque And Its Efficient Applications
  • What Is Class C++: Functions And Implementation
  • Understanding And Implementing Sort C++ In Your Code

Subscribe to our newsletter

Subscribe to be notified of new content on marketsplash..

IMAGES

  1. C Pointers

    assign pointer to memory address in c

  2. Pointers in C Programming with examples

    assign pointer to memory address in c

  3. C Pointer to Pointer (Theory & Example)

    assign pointer to memory address in c

  4. Pointer to a Function is an address of a function in memory [C/C++]

    assign pointer to memory address in c

  5. C

    assign pointer to memory address in c

  6. Pointers in C with Examples

    assign pointer to memory address in c

VIDEO

  1. Passing pointer to a function in C

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

  3. Notion de pointeur et utilisation des adresses mémoire en C

  4. Pointers in c language

  5. How to use pointer to allocate heap memory in c++

  6. print address using pointer#coding #subscribe #comment #youtuber #programmer #youtuber #art #sub100%

COMMENTS

  1. memory

    5. int *p=(int *)0x1234 = 10; //0x1234 is the memory address and value 10 is assigned in that address. unsigned int *ptr=(unsigned int *)0x903jf = 20;//0x903j is memory address and value 20 is assigned. Basically in Embedded platform we are using directly addresses instead of names. edited Nov 6, 2015 at 7:20. Suhas.

  2. C Pointers

    As the pointers in C store the memory addresses, their size is independent of the type of data they are pointing to. This size of pointers in C only depends on the system architecture. ... It is said to be good practice to assign NULL to the pointers currently not in use. 7. Void Pointer. The Void pointers in C are the pointers of type void. It ...

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

    Dereferencing a pointer means accessing the value stored at the memory address that the pointer points to. In C, you can think of pointers as variables that store memory addresses rather than actual values. To get the actual value (data) stored at that memory address, you need to dereference the pointer.

  4. 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.

  5. How to Use Pointers in C Programming

    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: int *p; int* p;

  6. Chapter 8: Pointers and Memory Allocation · Learning C with Pebble

    Pointers are typed in C. When a pointer is declared, the data type it points to is recorded. As with other variables, if we try to assign values from incompatible types, errors will result. Pointer Arithmetic. We have said that a pointer contains an address into memory. If addresses are just numbers, then we can do computations with them.

  7. C Pointers and Memory Allocation

    It is not the data itself. In C, the value in a pointer that represents the reference is often called an address, since computer memory is accessed using addresses that denote which memory location is being accessed. A special value of 0 is called the null pointer, also known as NULL and "nil". If a pointer has the value of 0, it is known to ...

  8. 7.0 Pointers

    Well, there are many different ways of assigning a memory address to a pointer. The most basic way was show to you in the first illustration of this chapter. int i = 5; ip = &i; C can get the memory address of a variable by referencing it. The amperstand is used as the referencing operator and it is placing in front of the varialbe that you ...

  9. Pointers in C: Your Guide to Efficient Memory Management in Programming

    Pointers in C: Efficient Memory Management Programming Guide; source: onlinefreenotes.com. Pointers, pointers, pointers😅. As any C programmer will tell you, pointers and memory management are topics that seem scary but are inevitable if you want to advance as a programmer. ... Assign a value of an address to the pointer; Access the value at ...

  10. Pointer in C Programming Language with Practical Examples

    Pointers can be initialized by assigning the memory address of a variable to them. The address-of operator (&) is used for this purpose. int var = 15; int *ptr = &var; Here, when we assign &var to a pointer variable ptr it stores the memory address ( 1001) of the variable. Now, we can indirectly manipulate data in the address 1001 through ptr.

  11. C Memory Address

    When a variable is created in C, a memory address is assigned to the variable. The memory address is the location of where the variable is stored on the computer. When we assign a value to the variable, it is stored in this memory address. To access it, use the reference operator ( & ), and the result represents where the variable is stored:

  12. Can an address be assigned to a variable in C?

    C language provides you with no means for "attaching" a name to a specific memory address. I.e. you cannot tell the language that a specific variable name is supposed to refer to a lvalue located at a specific address. So, the answer to your question, as stated, is "no". End of story.

  13. PDF Memory and Addresses Pointers in C 1

    Pointers in C Computer Organization I 1 CS@VT ©2005-2020 WD McQuain Memory and Addresses Memory is just a sequence of byte-sized storage devices. The bytes are assigned numeric addresses, starting with zero, just like the indexing of the cells of an array. It is the job of the operating system (OS) to: - manage the allocation of memory to ...

  14. Pointers in C Programming

    In typical memory architecture, each byte of memory has an address indexed by a number. Name binding : When we assign a value to them, the binary representation of this value will be written into ...

  15. A Complete Guide to Pointers in C

    Everything you need to know about pointers. Vishesh Raghuvanshi · Sep 22, 2023 · Sep 22, 2023 · 3 min read

  16. Pointers: Understanding Memory Addresses

    The pointer p also consumes 4 bytes (on most machines in use today, a pointer consumes 4 bytes of memory. Memory addresses are 32-bits long on most CPUs today, although there is a increasing trend toward 64-bit addressing). The location of i has a specific address, in this case 248,440. The pointer p holds that address once you say p = &i;. The ...

  17. Exploring C

    Step 1: Declare and initialize a pointer variable. The first step is to declare and initialize a pointer variable. This involves both declaring the pointer and assigning it a valid memory address. Take a look at the following example: int main() { int num = 20; // Declare and initialize a variable int *ptr = # // Declare and initialize a ...

  18. 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 ...

  19. How to initialize a pointer to a specific memory address in C++

    1. I would add that you can call the placement operator for new if you want an objects constructor called when assigning it at the specified address: int *pLoc = reinterpret_cast<int*>(0x604769); int *address = new (pLoc) int (1234); // init to a value. This is also used for memory caching objects. Create a buffer and then assign an object to it.

  20. Dynamic Memory Allocation in C using malloc(), calloc(), free() and

    Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the pointer ptr holds the address of the first byte in the allocated memory. If space is insufficient, allocation fails and returns a NULL pointer. Example of malloc() in C. C. #include <stdio.h>

  21. What Is Pointers In C++ And How To Use It

    What Is Pointers In C++; Pointer Initialization; Syntax And Indirection; Pointers And Function Arguments; A pointer in C++ is a variable that stores a memory address, serving as a direct link to the value stored at that location. It functions as a gateway, allowing us to read and write to the memory locations it points to.

  22. How to Assign an array to specific memory address in C

    1. Unless you are managing your memory allocation regions, say with linker scripts or other means, you should not do it. Compiler takes care of all memory allocation for you and does not provide any means for pre-defined memory addresses. However, if you know what you are doing, you can use a pointer to handle it: int *array = (int*)0x2000000;

  23. Rust Arc pointer comparison fails despite same memory address

    I figured I could use a trait and, for each object, assign a "target" as a weak pointer to the next item in the chain. Everything was going as expected until I decided to do some basic unit tests. I wanted to verify if the assigned weak pointer (upgraded to an Arc) was the same as the original instance.