Can't sort array without temp variable using pointer - c

The algorithm to swap the values of two integers x and y without using a tmp variable is
x = x + y;
y = x - y;
x = x - y;
I've written a code to sort an array by passing it to a method. The method accepts the array in a pointer *ptr. Thus, the elements of the array, arr[0], arr[1],... would be accessed with the pointer variable as *(ptr + 0), *(ptr + 1),.... However, the problem I'm facing is that when I try to swap the values of the array while sorting by referencing the memory location with a pointer, without the use of a temporary variable, the array is not getting sorted the way I expect and, instead, I see some random elements getting inserted into the array.
This is my array sorting code (selection sort - the sort algorithm is correct):
void sort(int *arr, int n){
int i,j,m;
for(i=0; i<n-1; i++){
m = i;
for(j=i+1; j<n; j++){
if(arr[j] < arr[m])
m = j;
}
//swapping arr[i] and arr[m]
*(arr + i) = *(arr + i) + *(arr + m);
*(arr + m) = *(arr + i) - *(arr + m);
*(arr + i) = *(arr + i) - *(arr + m);
}
//print the array...
}
void main(){
int arr[] = {2,4,3,5,8,7};
sort(arr, 6);
}
INPUT:
2 4 3 5 8 7
EXPECTED OUTPUT:
2 3 4 5 7 8
OBTAINED OUTPUT:
0 3 0 0 7 8
Why is this happening? What am I doing wrong?

The algorithm to swap the values of two integers x and y without using a tmp variable is
x = x + y;
y = x - y;
x = x - y;
One of several problems with this approach is that it does not work when x and y expressions refer to the same memory location. This is exactly what happens when an item is in its place after completion of the nested loop, i.e. when i is the same as m.
Adding if (i == m) continue before going into the swap will fix this problem.
Demo.

Related

Pointers to an Array In C

So my book is explaining me pointers to an array using ts example
#include <stdio.h>
int main()
{
int s[4][2] = {
{1234,56},{1212,33},{1434,80},{1312,78}
};
int(*p)[2];
int i, j, * pint;
for (i = 0; i <= 3; i++)
{
p = &s[i];
pint = (int*)p;
printf("\n");
for (j = 0; j<= 1; j++)
{
printf("%d ", *(pint + j));
}
}
return 0;
}
The output is Given as
1234 56
1212 33
1434 80
1312 78
No issue I am getting the same output.
My question is what was the need of using another pointer pint ?
Why can't we directly use P?
So When I tried to do it using P directly it didn't work
printf("%d ", *(p + j));
I got garbage values in output, Why is this happening?
I also tried printing p and pint they are the same.
Although p and pint have the same value, p + 1 and pint + 1 do not. p + 1 is the same as (char *)p + sizeof *p, and pint + 1 is the same as (char *)pint + sizeof *pint. Since the size of the object pointed to is different, the arithmetic gives different results.
The pointer p is declared like
int(*p)[2];
So dereferencing the pointer expression with the pointer in this call of printf
printf("%d ", *(p + j));
you will get the j-th "row" of the type int[2] of the two dimensional array that in turn will be implicitly converted to a pointer of the type int * that will point to the first element of the j-th "row".
So instead of outputting elements of each row you will output first elements of each row that moreover results in undefined behavior when i will be greater than 2.

How many pointers are in an array of pointers

I dynamically allocated memory for 3D array of pointers. My question is how many pointers do I have? I mean, do I have X·Y number of pointers pointing to an array of double or X·Y·Z pointers pointing to a double element or is there another variant?
double*** arr;
arr = (double***)calloc(X, sizeof(double));
for (int i = 0; i < X; ++i) {
*(arr + i) = (double**)calloc(Y, sizeof(double));
for (int k = 0; k < Y; ++k) {
*(*(arr+i) + k) = (double*)calloc(Z, sizeof(double));
}
}
The code you apparently intended to write would start:
double ***arr = calloc(X, sizeof *arr);
Notes:
Here we define one pointer, arr, and set it to point to memory provided by calloc.
Using sizeof (double) with this is wrong; arr is going to point to things of type double **, so we want the size of that. The sizeof operator accepts either types in parentheses or objects. So we can write sizeof *arr to mean “the size of a thing that arr will point to”. This always gets the right size for whatever arr points to; we never have to figure out the type.
There is no need to use calloc if we are going to assign values to all of the elements. We can use just double ***arr = malloc(X * sizeof *arr);.
In C, there is no need to cast the return value of calloc or malloc. Its type is void *, and the compiler will automatically convert that to whatever pointer type we assign it to. If the compiler complains, you are probably using a C++ compiler, not a C compiler, and the rules are different.
You should check the return value from calloc or malloc in case not enough memory was available. For brevity, I omit showing the code for that.
Then the code would continue:
for (ptrdiff_t i = 0; i < X; ++i)
{
arr[i] = calloc(Y, sizeof *arr[i]);
…
}
Notes:
Here we assign values to the X pointers that arr points to.
ptrdiff_t is defined in stddef.h. You should generally use it for array indices, unless there is a reason to use another type.
arr[i] is equivalent to *(arr + i) but is generally easier for humans to read and think about.
As before sizeof *arr[i] automatically gives us the right size for the pointer we are setting, arr[i].
Finally, the … in there is:
for (ptrdiff_t k = 0; k < Y; ++k)
arr[i][k] = calloc(Z, sizeof *arr[i][k]);
Notes:
Here we assign values to the Y pointers that arr[i] points to, and this loop is inside the loop on i that executes X times, so this code assigns XY pointers in total.
So the answer to your question is we have 1 + X + XY pointers.
Nobody producing good commercial code uses this. Using pointers-to-pointers-to-pointers is bad for the hardware (meaning inefficient in performance) because the processor generally cannot predict where a pointer points to until it fetches it. Accessing some member of your array, arr[i][j][k], requires loading three pointers from memory.
In most C implementations, you can simply allocate a three-dimensional array:
double (*arr)[Y][Z] = calloc(X, sizeof *arr);
With this, when you access arr[i][j][k], the compiler will calculate the address (as, in effect, arr + (i*Y + j)*Z + k). Although that involves several multiplications and additions, they are fairly simple for modern processors and are likely as fast or faster than fetching pointers from memory and they leave the processor’s load-store unit free to fetch the actual array data. Also, when you are using the same i and/or j repeatedly, the compiler likely generates code that keeps i*Y and/or (i*Y + j)*Z around for multiple uses without recalculating them.
Well, short answer is: it is not known.
As a classic example, keep in mind the main() prototype
int main( int argc, char** argv);
argc keeps the number of pointers. Without it we do not know how many they are. The system builds the array argv, gently updates argc with the value and then launches the program.
Back to your array
double*** arr;
All you know is that
arr is a pointer.
*arr is double**, also a pointer
**arr is double*, also a pointer
***arr is a double.
What you will get in code depends on how you build this. A common way if you need an array of arrays and things like that is to mimic the system and use a few unsigned and wrap them all with the pointers into a struct like
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
A CSV file for example is char ** **, a sheet workbook is char ** ** ** and it is a bit scary, but works. For each ** a counter is needed, as said above about main()
A C example
The code below uses arr, declared as double***, to
store a pointer to a pointer to a pointer to a double
prints the value using the 3 pointers
then uses arr again to build a cube of X*Y*Z doubles, using a bit of math to set values to 9XY9.Z9
the program uses 2, 3 and 4 for a total of 24 values
lists the full array
list the first and the very last element, arr[0][0][0] and arr[X-1][Y-1][Z-1]
frees the whole thing in reverse order
The code
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
int print_array(double***, int, int, int);
int main(void)
{
double sample = 20.21;
double* pDouble = &sample;
double** ppDouble = &pDouble;
double*** arr = &ppDouble;
printf("***arr is %.2ff\n", ***arr);
printf("original double is %.2ff\n", sample);
printf("*pDouble is %.2ff\n", *pDouble);
printf("**ppDouble is %.2ff\n", **ppDouble);
// but we can build a cube of XxYxZ doubles for arr
int X = 2;
int Y = 3;
int Z = 4; // 24 elements
arr = (double***)malloc(X * sizeof(double**));
// now each arr[i] must point to an array of double**
for (int i = 0; i < X; i += 1)
{
arr[i] = (double**)malloc(Y * sizeof(double*));
for (int j = 0; j < Y; j += 1)
{
arr[i][j] = (double*)malloc(Z * sizeof(double));
for (int k = 0; k < Z; k += 1)
{
arr[i][j][k] = (100. * i) + (10. * j) + (.1 * k) + 9009.09;
}
}
}
print_array(arr, X, Y, Z);
printf("\n\
Test: first element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n\
last element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n",
0, 0, 0, arr[0][0][0],
(X-1), (Y-1), (Z-1), arr[X-1][Y-1][Z-1]
);
// now to free this monster
for (int x = 0; x < X; x += 1)
{
for (int y = 0; y < Y; y += 1)
{
free(arr[x][y]); // the Z rows
}
free(arr[x]); // the plane Y
}
free(arr); // the initial pointer;
return 0;
}; // main()
int print_array(double*** block, int I, int J, int K)
{
for (int a = 0; a < I; a += 1)
{
printf("\nPlane %d\n\n", a);
for (int b = 0; b < J; b += 1)
{
for (int c = 0; c < K; c += 1)
{
printf("%6.2f ", block[a][b][c]);
}
printf("\n");
}
}
return 0;
}; // print_array()
The output
***arr is 20.21f
original double is 20.21f
*pDouble is 20.21f
**ppDouble is 20.21f
Plane 0
9009.09 9009.19 9009.29 9009.39
9019.09 9019.19 9019.29 9019.39
9029.09 9029.19 9029.29 9029.39
Plane 1
9109.09 9109.19 9109.29 9109.39
9119.09 9119.19 9119.29 9119.39
9129.09 9129.19 9129.29 9129.39
Test: first element is arr[0][0[0] = 9009.09 (9XY9.Z9)
last element is arr[1][2[3] = 9129.39 (9XY9.Z9)

How do I make a 2D array initialization function with pointers?

I'm trying to make a function that takes in the pointer of the 2d array and the integers y and x based on the size of the array. I keep getting errors here and was hoping someone could help me out. the function randNum just returns a random integer from 0 to 9.
void initialize(int t[], int y, int x){
for(p = &t[0][0]; p <= &t[y-1][x-1]; p++){
*(t + ((y*x) + x)) = randomNum(0,9);
}
}
void initialize(int t[], int y, int x){
for(int *i = t, i < t + x * y; i++)
*i = randomNum(0,9);
}
Explanation:
Your array contains x times y integers, so it is a memory segment containing those. Thus, we can see it as an one dimensional array of size x*y.
Your code does not work because for instance the compiler would have no way to determine what
&t[y-1][x-1]
even is. For an integer array a the compiler would know that for
*(a + k) == a[k]
it would need to take the address of a and add k times the size of an integer (usually 4 bytes). For
a[k][l]
we would need to take
*(a + innerdimension * k + l)
but as the compiler does not know what the inner dimension is it cannot work.
Alternatively you could also go for something like
void intitialize(int *t, int y, int x){
for(int i = 0; i < y; i++)
for (int j = 0; j < x; j++)
*(t + i * x + j) = randomNum(0,9);
}
While this is a bit longer it would exactly describe how you would iterate over an 2D array while replacing the not working t[i][j] by its equivalent (t + ix + j) given a known inner dimension x.

Copying data from 1st to 2nd array using Pointer arithemtic

I am learning C, and I came across this problem I can't figure it out. Write a function that computes the element of an integer array a plus 6 modulus 10 and store the result in array b. For example, if 5 is the second element of array a, then the second element of array b should be (5+6)%10, which is 1. The function has the following prototype, n is the length of the arrays, a and b are the integer arrays.
I did:
void arithmetic (int *a, int n, int *b)
{
int *arr1; arr1=a; int *arr2; arr2=b;
int i;
for(i = 0; i < n; i++) {
*arr1 = *(((a + i) + 6) % 10);
*arr2 = *arr1;
}
}//don't know if the function is correct.
A couple things:
No need to update the actual content of the first array (which fixes the error pointed out about your code always storing the result in the first element of a)
Use some parens to make sure you get the right order of operations.
void newArr(int *a, int n, int *b) {
int *arr1; arr1 = a; int *arr2; arr2 = b;
for (int i = 0; i < n; i++) {
*(arr2 + i) = (*(arr1 + i) + 6) % 10;
}
}
Think about your title "...using Pointer arithemtic". You need to add the loop counter to the array pointer for both arr1 and arr2 so that it steps through each element of each array: *(arr2 + i) and *(arr1 + i).
This is also a good place to reinforce the fact that the pointers are passed by value and that the function receives copy of each pointer which it is free to iterate with to affect the copy without effecting the pointers in the caller. So it would also be perfectly valid to do:
void arithmetic (int *a, int *b, size_t n)
{
if (!a || !b)
return;
for(size_t i = 0; i < n; i++, a++, b++)
*b = (*a + 6) % 10;
}
(good job Pablo with the use of size_t for the length (or number of elements) parameter)
No, your function is not correct.
*arr1 = *((a+i)+6)%10);
You are only writing the values in the first element of the array.
arr1 points to a which already has the values. You want to do the
calculation with a value stored in a and then save it to b, so don't modify
a.
*((a+i+6)%10) is completely wrong. a+i+6 is the same as &a[i+6]. The %10
applies to the value &a[i+6] (which is the address of the i+6th element), and returns a value between 0 and 9 (let's call
it x). When do *(x) you are interpreting the x as a pointer and it
dereferences (=access the value through the pointer) it, but this is not a valid
address at all. You will also eventually access a out of bounds.
*arr2 = *arr1; here you also only storing the values in the first element of arr2.
You function has no name.
int *arr1; arr1=a; this is unnecessary, you can access a directly, no
need to create a copy of the pointer.
The +6 % 10 rule applies to the values stored in the array, not the indices.
The correct function should look like this:
void compute(int *a, int *b, size_t len)
{
if(a == NULL || b == NULL)
return;
for(size_t i = 0; i < len; ++i)
b[i] = (a[i] + 6) % 10;
}
And if your assignment says you should do it with pointer arithmetic instead of
using array indexing:
void compute(int *a, int *b, size_t len)
{
if(a == NULL || b == NULL)
return;
for(size_t i = 0; i < len; ++i)
*(b+i) = (*(a + i) + 6) % 10;
}

Using pointers to matrices in a scanf function

I was playing around with pointers when inputing a matrix with scanf and for some reason, when I run this code, only the first element of every row gets stored correctly.
#include "stdio.h"
void main()
{
int i, j, n, A[10][10];
scanf("%d", &n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", A + j + i*10);
}
This is what I get after inputing 1,2,3,4,5,6,7,9 into a 3x3 matrix and printing it:
1 -858993460 -858993460
2 -858993460 -858993460
3 -858993460 -858993460
According to my understanding of how matrices are stored, this should work. Can anyone point out whats wrong with my code?
You declare A as
int A[10][10];
that is, an array of 10 arrays of 10 ints each. Thus, when A decays to a pointer to its first element, the type of that pointer is int (*)[10]. That's a pointer to an array of 10 ints, not a pointer to a single int. Among the differences is their interaction with pointer arithmetic. Because pointer arithmetic is defined in terms of the size of the pointed-to type, whenever i is nonzero, the expression A + j + i*10 produces a pointer (to array of 10 ints) outside the bounds of array A.
The most type-safe way of doing what you want would be to use array syntax to select array elements:
&A[i][j]
. Type-correct alternatives that use pointer arithmetic include
&(*(A + i))[j]
and
*(A + i) + j
These latter two both rely on the fact that the expression A + i is a pointer to an array of int; dereferencing that pointer produces an array, which can be the operand of the [] operator (and the address of the result then taken). Alternatively, the array designated by *(A + i) decays to a pointer to its first element (i.e. decays to an int *) when it appears as an operand of the + operator, and adding j to that yields a pointer to the jth element of array *(A + i) (which is the same array designated by A[i]).
Bad pointer math.
A + j + i * 10
When A is used in A + j + i*10, it becomes the pointer to its first element, which is an array of 10 int. Every 1 added to A offsets its address by 40 bytes.
Recommend to use &A[i][j] instead.
Code re-worked to show addresses used.
#include "stdio.h"
int main() {
int i, j, n, A[10][10];
n = 3;
char *base = (char*) A;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) {
char *offset0 = (char*) (&A[i][j]);
char *offset1 = (char *) (A + j + i * 10);
printf("%d %d %3td %3td\n", i, j, offset0 - base, offset1 - base);
}
}
Output
0 0 0 0
0 1 4 40
0 2 8 80
1 0 40 400
1 1 44 440
1 2 48 480
2 0 80 800
2 1 84 840
2 2 88 880

Resources