# Pointer Arithmetic in C

Pointer arithmetic in C allows you to perform arithmetic operations on pointers to navigate through memory locations. It is primarily used to iterate over arrays, access elements in data structures, and dynamically allocate memory.

In C, when you perform arithmetic operations on pointers, the compiler adjusts the memory address based on the size of the data type being pointed to. The general syntax for pointer arithmetic is as follows:

```pointer = pointer +/- integer_value;
```

Here are a few examples to illustrate pointer arithmetic:

1. Incrementing a pointer:
```int array[] = {10, 20, 30, 40, 50};
int *ptr = array;  // Points to the first element of the array

// Incrementing the pointer
ptr++;  // Moves the pointer to the next element in the array

// Accessing the value using the incremented pointer
printf("%d\n", *ptr);  // Output: 20
```
1. Decrementing a pointer:
```int array[] = {10, 20, 30, 40, 50};
int *ptr = &array[4];  // Points to the last element of the array

// Decrementing the pointer
ptr--;  // Moves the pointer to the previous element in the array

// Accessing the value using the decremented pointer
printf("%d\n", *ptr);  // Output: 40
```
1. Arithmetic operations on pointers:
```int array[] = {10, 20, 30, 40, 50};
int *ptr = array + 2;  // Points to the third element of the array

// Accessing the value using the pointer
printf("%d\n", *ptr);  // Output: 30

// Adding an integer value to the pointer
ptr = ptr + 2;  // Moves the pointer two elements forward

// Accessing the value using the updated pointer
printf("%d\n", *ptr);  // Output: 50
```

It’s important to note that pointer arithmetic should be used with caution to ensure you stay within the valid memory bounds of the array or data structure. Incrementing or decrementing a pointer beyond the bounds of the allocated memory can lead to undefined behavior and potentially crash your program.

### Incrementing Pointer in C:

In C, you can increment a pointer by using the increment operator `++`. Incrementing a pointer moves it to the next memory location based on the size of the data type it points to.

Here’s an example that demonstrates how to increment a pointer:

```#include <stdio.h>

int main() {
int array[] = {10, 20, 30, 40, 50};
int *ptr = array;  // Points to the first element of the array

printf("Before increment: %d\n", *ptr);  // Output: 10

ptr++;  // Incrementing the pointer

printf("After increment: %d\n", *ptr);  // Output: 20

return 0;
}
```

In this example, `ptr` is initially pointing to the first element of the `array`. After incrementing `ptr` using `ptr++`, it now points to the next element in the array, which is `20`. The `*ptr` expression is used to dereference the pointer and retrieve the value it points to.

It’s worth noting that the amount by which the pointer is incremented depends on the size of the data type it points to. For example, if the pointer is of type `int*`, incrementing it will move it forward by the size of an `int` (typically 4 bytes on most systems).

Pointer arithmetic can be particularly useful when iterating over arrays or accessing elements in data structures. Just be cautious not to go beyond the valid memory bounds of the allocated memory, as doing so can result in undefined behavior.

### Traversing an array by using pointer:

Certainly! Traversing an array using pointers in C is a common technique that allows you to iterate through the elements of an array by incrementing a pointer. Here’s an example:

```#include <stdio.h>

int main() {
int array[] = {10, 20, 30, 40, 50};
int *ptr = array;  // Points to the first element of the array

// Traverse the array using a loop
for (int i = 0; i < 5; i++) {
printf("%d ", *ptr);  // Output each element
ptr++;  // Move to the next element
}

return 0;
}
```

In this example, we initialize a pointer `ptr` to point to the first element of the `array`. We then use a `for` loop to iterate through the array. Within each iteration, we print the value of the element pointed to by `ptr` using the `*ptr` syntax. After printing the element, we increment the pointer `ptr` using `ptr++` to move it to the next element in the array.

The output of the above code will be:

```10 20 30 40 50
```

By incrementing the pointer in each iteration, we can access and process each element of the array. This technique is particularly useful when you need to perform operations on each element of an array or when you want to avoid using array indexing.

Remember to ensure that the loop condition does not go beyond the valid memory bounds of the array to avoid undefined behavior.

### Decrementing Pointer in C:

In C, you can decrement a pointer by using the decrement operator `--`. Decrementing a pointer moves it to the previous memory location based on the size of the data type it points to.

Here’s an example that demonstrates how to decrement a pointer:

```#include <stdio.h>

int main() {
int array[] = {10, 20, 30, 40, 50};
int *ptr = &array[4];  // Points to the last element of the array

printf("Before decrement: %d\n", *ptr);  // Output: 50

ptr--;  // Decrementing the pointer

printf("After decrement: %d\n", *ptr);  // Output: 40

return 0;
}
```

In this example, `ptr` is initially pointing to the last element of the `array`. After decrementing `ptr` using `ptr--`, it now points to the previous element in the array, which is `40`. The `*ptr` expression is used to dereference the pointer and retrieve the value it points to.

Similar to incrementing, the amount by which the pointer is decremented depends on the size of the data type it points to. In the example above, `ptr` is of type `int*`, so decrementing it moves it backward by the size of an `int` (typically 4 bytes on most systems).

Decrementing pointers is useful in scenarios where you need to traverse an array in reverse order or navigate backward through a data structure. However, ensure that you do not go beyond the valid memory bounds of the allocated memory to avoid undefined behavior.

In C, you can perform pointer addition by adding an integer value to a pointer. Pointer addition allows you to navigate through memory locations by a specified offset, based on the size of the data type being pointed to.

Here’s an example that demonstrates pointer addition:

```#include <stdio.h>

int main() {
int array[] = {10, 20, 30, 40, 50};
int *ptr = array + 2;  // Points to the third element of the array

printf("Current value: %d\n", *ptr);  // Output: 30

ptr = ptr + 2;  // Adding 2 to the pointer

printf("Updated value: %d\n", *ptr);  // Output: 50

return 0;
}
```

In this example, we have an array of integers `array`. We initialize a pointer `ptr` to point to the third element of the array (`array + 2`). We use `ptr + 2` to perform pointer addition by adding an offset of 2 elements to the current position. After performing the addition, `ptr` now points to the fifth element of the array (`50`).

The key thing to note is that the integer value added to the pointer is automatically scaled by the size of the data type it points to. In this case, since `ptr` is of type `int*`, adding `2` to the pointer will move it forward by `2 * sizeof(int)` bytes.

Pointer addition can be useful when you want to access elements in an array or navigate through memory locations dynamically. However, make sure to stay within the bounds of valid memory to avoid undefined behavior.

### C Pointer Subtraction:

In C, you can perform pointer subtraction by subtracting one pointer from another or by subtracting an integer value from a pointer. Pointer subtraction allows you to calculate the distance or offset between two pointers or to move backward through memory locations.

Here are two examples that demonstrate pointer subtraction:

1. Subtracting two pointers:
```#include <stdio.h>

int main() {
int array[] = {10, 20, 30, 40, 50};
int *ptr1 = &array[4];  // Points to the last element of the array
int *ptr2 = &array[1];  // Points to the second element of the array

int diff = ptr1 - ptr2;  // Subtracting two pointers

printf("Pointer difference: %d\n", diff);  // Output: 3

return 0;
}
```

In this example, we have two pointers `ptr1` and `ptr2` pointing to different elements of the `array`. By subtracting `ptr2` from `ptr1` (`ptr1 - ptr2`), we calculate the difference or offset between the two pointers. The result, `3`, represents the number of elements between `ptr1` and `ptr2`.

1. Subtracting an integer value from a pointer:
```#include <stdio.h>

int main() {
int array[] = {10, 20, 30, 40, 50};
int *ptr = &array[4];  // Points to the last element of the array

ptr = ptr - 2;  // Subtracting 2 from the pointer

printf("Updated value: %d\n", *ptr);  // Output: 30

return 0;
}
```

In this example, we have a pointer `ptr` pointing to the last element of the `array`. By subtracting `2` from the pointer (`ptr - 2`), we move the pointer backward by `2 * sizeof(int)` bytes, effectively pointing to the third element of the array (`30`).

When subtracting two pointers, the result is typically divided by the size of the data type to determine the number of elements between them. Similarly, when subtracting an integer value from a pointer, the subtraction is scaled by the size of the data type.

Pointer subtraction can be useful for calculating offsets, determining the number of elements between pointers, or navigating through memory locations. Just ensure that the pointers you subtract are pointing to elements within the same array or valid memory locations to avoid undefined behavior.

### Illegal arithmetic with pointers:

In C, performing certain arithmetic operations with pointers can lead to undefined behavior or errors. Here are some examples of illegal arithmetic operations with pointers:

1. Multiplication or Division: Multiplying or dividing a pointer by a scalar value is not allowed in C. The meaning of such an operation is not well-defined because it does not align with the concept of navigating through memory locations.
```int *ptr = ...;
int result = ptr * 2;  // Illegal: Multiplication of pointer by scalar
```
1. Addition or Subtraction of Pointers of Different Types: Adding or subtracting pointers of different types is not allowed. Pointers are strongly typed, and arithmetic operations should only be performed between pointers of the same type.
```int *ptr1 = ...;
float *ptr2 = ...;
int *result = ptr1 + ptr2;  // Illegal: Addition of pointers of different types
```
1. Addition or Subtraction of Two Pointers: Adding or subtracting two pointers is illegal unless it is used to calculate the difference between them. The result of such an operation is a value representing the number of elements or bytes between the two pointers.
```int *ptr1 = ...;
int *ptr2 = ...;
int diff = ptr1 + ptr2;  // Illegal: Addition of two pointers
```
1. Incrementing or Decrementing a Non-Initialized Pointer: Performing pointer arithmetic on a pointer that has not been initialized or points to invalid memory is undefined behavior. Pointers should always be initialized before performing any arithmetic operations on them.
```int *ptr;  // Pointer not initialized
ptr++;    // Illegal: Incrementing a non-initialized pointer
```

It’s crucial to adhere to the rules of pointer arithmetic in C to ensure safe and well-defined behavior. Illegal pointer arithmetic can lead to program crashes, memory corruption, or other unpredictable results. Always make sure to use valid and properly initialized pointers when performing arithmetic operations.

### Pointer to function in C:

In C, you can use pointers to functions to store addresses of functions and invoke them through the pointer. This feature allows you to treat functions as variables, enabling dynamic function invocation and function callbacks.

Here’s an example that demonstrates the usage of a pointer to a function:

```#include <stdio.h>

int add(int a, int b) {
return a + b;
}

int subtract(int a, int b) {
return a - b;
}

int main() {
int (*operation)(int, int);  // Declaration of function pointer

printf("Result of addition: %d\n", operation(5, 3));  // Output: 8

operation = subtract;  // Assigning the address of 'subtract' function to the pointer
printf("Result of subtraction: %d\n", operation(5, 3));  // Output: 2

return 0;
}
```

In this example, we declare a function pointer named `operation` using the syntax `int (*operation)(int, int)`. This function pointer can point to functions that take two `int` arguments and return an `int`. We assign the address of the `add` function to the `operation` pointer using `operation = add;`, and then we invoke the function through the pointer as `operation(5, 3)`. Similarly, we assign the address of the `subtract` function to the `operation` pointer and invoke it.

Function pointers are useful when you want to select a function to execute at runtime based on certain conditions, implement callbacks or event handlers, or build function tables. They provide flexibility and allow for dynamic behavior in your program.

Note that when using function pointers, it is essential to ensure that the function pointer and the target function have compatible signatures (i.e., matching return type and parameter types).

### Pointer to Array of functions in C:

In C, you can use a pointer to an array of functions to create a mechanism for storing and accessing multiple functions through a single pointer. This can be useful when you want to switch between different functions dynamically or create function tables for lookup purposes.

Here’s an example that demonstrates the usage of a pointer to an array of functions:

```#include <stdio.h>

int add(int a, int b) {
return a + b;
}

int subtract(int a, int b) {
return a - b;
}

int multiply(int a, int b) {
return a * b;
}

int main() {
int (*operations[3])(int, int);  // Declaration of array of function pointers

operations[1] = subtract;  // Assigning the address of 'subtract' function to the array element
operations[2] = multiply;  // Assigning the address of 'multiply' function to the array element

int result = operations[0](5, 3);  // Invoking the 'add' function through the array element
printf("Result of addition: %d\n", result);  // Output: 8

result = operations[1](5, 3);  // Invoking the 'subtract' function through the array element
printf("Result of subtraction: %d\n", result);  // Output: 2

result = operations[2](5, 3);  // Invoking the 'multiply' function through the array element
printf("Result of multiplication: %d\n", result);  // Output: 15

return 0;
}
```

In this example, we declare an array of function pointers named `operations` using the syntax `int (*operations[3])(int, int)`. This array can store pointers to functions that take two `int` arguments and return an `int`. We assign the addresses of the `add`, `subtract`, and `multiply` functions to the respective elements of the `operations` array. We then invoke each function through the array element, passing the appropriate arguments.

By using a pointer to an array of functions, you can switch between different functions by accessing different elements of the array dynamically. This allows for flexible and dynamic function invocation based on runtime conditions or user input.

Note that all functions stored in the array must have compatible signatures (matching return type and parameter types).

Categories C