C: Trouble understanding pointers in this program - c

I need to find the values of i and j after the following code is executed:
int i = 2;
int j = 2;
int *p = &i;
int *q = &j;
i++;
j--;
*p = *q + 2;
*q = *p + 3;
p=q;
*p = *q + 1;
Let me describe what I think is happening in this code.
In the third and fourth line:
int *p = &i;
int *q = &j;
pointers p and q are initialized to the addresses of i and j, respectively.
In the 5th and 6th lines:
i++;
j--;
i becomes 3 and j becomes 1. This causes *p to be 3 and *q to be 1.
In the 7th line,
*p = *q + 2
means the value that p points to is equal to the value that q points to plus` 2, so i becomes 3.
In the next line:
*q = *p + 3;
j becomes 6.
I'm not sure what happens in this next line:
p = q;
I think it means: "the address of i is equal to address of j". I do not know what the final values of i and j would be in this situation. Can you help me understand what is happening?

Imagine your memory looks like this after the initial initialization of p and q:
+---+ +---+
| p | --> | i |
+---+ +---+
+---+ +---+
| q | --> | j |
+---+ +---+
After you do
p = q;
it looks like this instead:
+---+
| p | --\
+---+ \ +---+
>--> | j |
+---+ / +---+
| q | --/
+---+

p = q;
This simply means that now p is pointing to the same thing that q was pointing to, i.e. j.

Related

Pointer Logic Exercise in C

I am trying to understand pointers and the different declarations. I was provided with an example with pointer logic but I cannot figure out how it works exactly.
I was giving the following piece:
int i, j, *p, *q;
i = 10;
p = &j;
q = malloc(sizeof(int));
*q = i;
j = i;
q = p;
*q = 5;
printf("%d %d %d %d", i, j, *p, *q);
It says that the outcome is 10 5 5 5 but I canno get behind why.
Thank you in advance!
Drawing is the best way to figure out pointer manipulation.
(It's much faster on paper, though.)
i j
+----+ +----+
| 10 | | |
+----+ +----+
[p = &j; p is the location of j]
i j
+----+ +----+
| 10 | | |
+----+ +----+
^
|
p
[q = malloc(sizeof(int)); q is the location of an unnamed int]
i j
+----+ +----+ +----+
| 10 | | | | |
+----+ +----+ +----+
^ ^
| |
p q
[*q = i; replace the value of the int that q points to with i's value]
i j
+----+ +----+ +----+
| 10 | | | | 10 |
+----+ +----+ +----+
^ ^
| |
p q
[j = i; replace the value of j with the value of i]
i j
+----+ +----+ +----+
| 10 | | 10 | | 10 |
+----+ +----+ +----+
^ ^
| |
p q
[q = p; replace the value of q with the value of p, i.e. they are both &j]
i j
+----+ +----+ +----+
| 10 | | 10 | | 10 |
+----+ +----+ +----+
^ ^
| |
p q
[*q = 5; replace the value of the int that q points to with 5]
i j
+----+ +----+ +----+
| 10 | | 5 | | 10 |
+----+ +----+ +----+
^ ^
| |
p q
Notice three statements:
p = &j;
q = p;
*q = 5;
So, *q, which is the same as *p, which points to j, is set to a value of 5.
So, all the three expression, j, *p, *q yields the same value.
Below is a step by step explanation of what the code does and how the value of the variables change. I'll recommend that you use a debugger and single step the code and inspect each variable after each step.
But here it goes:
// Define two int variables (i and j) and two int-pointer variables (p and q)
int i, j, *p, *q; // i: uninitialized j: uninitialized p: uninitialized q: uninitialized
// Assign 10 to i
i = 10; // i: 10, j: uninitialized, p: uninitialized, q: uninitialized
// Make p point to j
p = &j; // i: 10, j: uninitialized, p: points to j, q: uninitialized
// Allocate some memory for q
q = malloc(sizeof(int)); // i: 10, j: uninitialized, p: points to j, q: points to uninitialed memory
// Assign i to the memory that q points to
*q = i; // i: 10, j: uninitialized, p: points to j, q: points to memory containing 10
// Assign i to j
j = i; // i: 10, j: 10, p: points to j, q: points to memory containing 10
// Make q point to the same as p
q = p; // i: 10, j: 10, p: points to j, q: points to j
// Assign 5 to the memory that q points to (which is j)
*q = 5; // i: 10, j: 5, p: points to j, q: points to j
// print i (10), j (5), the memory p points to (j aka 5), the memory q points to (j aka 5)
printf("%d %d %d %d", i, j, *p, *q); // Print 10 5 5 5
Notice:
q = p;
represents a memory leak as there no longer is a pointer to the dynamic allocated memory.

How to allocate memory using a pointer to pointer in C

I am trying to understand code snippets in
free a double pointer
and
Why use double pointer? or Why use pointers to pointers?
I want to understand the difference between the following. Both snippets are from the above urls
int** pt;
pt = (int*) malloc(sizeof(int)*10);
and
*pt = (int*) malloc(sizeof(int)*10);
Could you elaborate with some examples and drawing
First of all, the code snippet is bad for several reasons - the first is casting the result of malloc to the wrong type, and is using the wrong type to compute the amount of memory. Fixing the cast and type issues, we have:
int **pt;
pt = malloc( sizeof *pt * 10 ); // allocate space for 10 int *
*pt = malloc( sizeof **pt * 10 ); // allocate space for 10 int
After executing the first line, you have the following:
int ** int *
+---+ +---+
pt: | | --------------->| | pt[0]
+---+ +---+
| | pt[1]
+---+
| | pt[2]
+---+
...
+---+
| | pt[9]
+---+
You've set aside space for 10 int * objects, and pt points to the first of them.
The next line
*pt = malloc( sizeof **pt * 10 ); // allocate space for 10 int
allocates space for 10 int objects, and sets pt[0] to point to them:
int ** int * int
+---+ +---+ +---+
pt: | | --------------->| | pt[0] -------->| | pt[0][0]
+---+ +---+ +---+
| | pt[1] | | pt[0][1]
+---+ +---+
| | pt[2] | | pt[0][2]
+---+ +---+
... ...
+---+ +---+
| | pt[9] | | pt[0][9]
+---+ +---+
This illustrates one way of allocating a "jagged" array; you can still index it as pt[i][j], but unlike a true 2D array the rows are not adjacent in memory, and each row may be a different length. You'd normally write that as
pt = malloc( sizeof *pt * ROWS );
if ( pt )
{
for ( size_t r = 0; r < ROWS; r++ )
{
pt[r] = malloc( sizeof *pt[r] * COLS );
}
}
When that's all done, you have something like this:
int ** int * int
+---+ +---+ +---+---+ +---+
pt: | | ---------> | | pt[0] --------> | | | ... | | pt[0][0] - pt[0][COLS-1]
+---+ +---+ +---+---+ +---+
| | pt[1] ------+
+---+ | +---+---+ +---+
| | pt[2] ---+ +-> | | | ... | | pt[1][0] - pt[1][COLS-1]
+---+ | +---+---+ +---+
... |
| +---+---+ +---+
+----> | | | ... | | pt[2][0] - pt[2][COLS-1]
+---+---+ +---+
The following is wrong, compiler should complain about types:
int** pt;
pt = (int*) malloc(sizeof(int)*10);
This is also wrong for another reason (here pt does not actually point to anything usable):
int** pt;
*pt = (int*) malloc(sizeof(int)*10);
A pointer to T is a variable of type T * that may contain address of some memory that may contains elements of type T:
+------+
| | pointer to T
+------+
|
v
+-------------+-------------+-------------+
| | | | elements of type T
+-------------+-------------+-------------+
For example, in C, to obtain what is drawn, you can write:
int *pi;
pi = malloc(sizeof(int)*3);
If you have a pointer to pointer to T then then diagram could be something like:
+------+
| | pointer to pointer to T
+------+
|
v
+------+------+------+
| | | | pointers to T
+------+------+------+
| | | +-------------+-------------+-------------+
| | +---->| | | | elements of type T
| | +-------------+-------------+-------------+
| | +-------------+-------------+
| +---->| | | elements of type T
| +-------------+-------------+
|
v
+-------------+-------------+-------------+-------------+
| | | | | elements of type T
+-------------+-------------+-------------+-------------+
and the code could be:
int **ppi;
ppi = malloc(sizeof(int *)*3);
ppi[0] = malloc(sizeof(int)*3);
ppi[1] = malloc(sizeof(int)*2);
ppi[2] = malloc(sizeof(int)*4);
Of course, malloc could fail and return value should be tested against failure.
Using the casting you helped the compiler to find an error in this code snippet
int** pt;
pt = (int*) malloc(sizeof(int)*10);
For example the error message can look like
error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
pt = (int*) malloc(sizeof(int)*10);
^
Without the casting the compiler could accept this evidently invalid code because the return type of the function malloc is void * and a pointer of the type void * may be assigned to a pointer to object of any other type.
That is in the right side of the assignment the evaluated expression has the type int * while in the left side of the assignment there is an object of the type int ** and there is no implicit conversion from the type int * to the type int **.
This code snippet
int** pt;
*pt = (int*) malloc(sizeof(int)*10);
is invalid by another reason. The pointer pt is not initialized by a valid address of an object. It has either indeterminate value if the pointer has automatic storage duration or NULL if the pointer has static storage duration. In any case its dereferencing results in undefined behavior.
So it would be correctly to write
int* pt;
^^^^^^^
pt = (int*) malloc(sizeof(int)*10);
However this construction
int** pt;
//...
*pt = (int*) malloc(sizeof(int)*10);
can be made valid in some context.
Let's assume that you declared a pointer
int *pt;
and want to initialize it in a function. In this case you have to pass the pointer to the function by reference. Otherwise the function will deal with a copy of the pointer and in this case the original pointer will not be assigned in the function.
So the corresponding code snippet can look as it is shown in the demonstrative program
#include <stdlib.h>
#include <stdio.h>
size_t f( int **pt )
{
const size_t N = 10;
*pt = (int*) malloc( sizeof( int ) * N );
if ( *pt )
{
int value = 0;
for ( size_t i = 0; i < N; i++ ) ( *pt )[i] = value++;
}
return *pt == NULL ? 0 : N;
}
int main( void )
{
int *pt;
size_t n = f( &pt );
if ( n )
{
for ( size_t i = 0; i < n; i++ ) printf( "%d ", pt[i] );
putchar( '\n' );
}
free( pt );
}
The program output is
0 1 2 3 4 5 6 7 8 9

Unexpected output from test program with pointers and levels of indirection in C

#include<stdio.h>
int main()
{
int z; int **x; int *y;
x = (int **) malloc(sizeof(int*));
*x = malloc(sizeof(int));
**x = 5;
y = *x; //POINT 1
z = 3;
*x = &z;//POINT 2
printf("%d\n",*y);
printf("%d\n", **x);
**x = 2;
printf("%d\n",*y);
*y=1;
printf("%d\n",z);
}
Output I get is as follows
5 // why is this 5?
3
5
2
My question is shouldn't the first output print 3? Why is 5 being printed?
My question is does this program produce dangling reference or garbage? I am thinking that might be one of the reasons for this unexpected output. Can someone please explain.
Lets draw it out.
After you initialize x, *x and **x you memory looks something like this:
+---+ +----+ +---+
| x | --> | *x | --> | 5 |
+---+ +----+ +---+
The you assign y:
+---+ +----+
| x | --> | *x | --\
+---+ +----+ \ +---+
>--> | 5 |
+---+ / +---+
| y | --/
+---+
And then you make *x points somewhere else, so you have this:
+---+ +----+ +---+
| x | --> | *x | --> | z |
+---+ +----+ +---+
+---+ +---+
| y | --> | 5 |
+---+ +---+
In other words, you make y point to where *x is pointing, not to *x itself, so when you change where *x is pointing you don't change where y is pointing.
x points to a pointer(say p) that points to memory location. You stored the value 5 in that location.
y points to the location where the pointer p is pointing, a location with value 5.
z is a memory location with value 3.
Now p is made to point to the memory location of z. But this DOES NOT change where y is pointing. Hence it still points to a location with value 5.
In your program you have y = *x; which puts the pointer pointed to by x into the pointer variable y. That area of memory pointed to by the pointer in x has a value of 5 since y now has that pointer, then *y is now 5. You then put a new pointer into the pointer area that is pointed to by x.
int main()
{
int z; int **x; int *y;
x = (int **) malloc(sizeof(int*)); // create a pointer to a pointer variable
*x = malloc(sizeof(int)); // create a pointer to an int that is put into the pointer that is pointed to by x ( x -> int pointer -> int )
**x = 5; // set the int value pointed to by the pointer that is pointed to by x to 5
y = *x; //POINT 1 // assign the pointer to the int value to another pointer variable
z = 3;
*x = &z;//POINT 2 // assign a new address to the pointer that is pointed to by x.
printf("%d\n",*y); // print the value pointed to by y which is 5
printf("%d\n", **x); // print the value that is pointed to by the pointer which is pointed to by x which is 3
**x = 2;
printf("%d\n",*y);
*y=1;
printf("%d\n",z);
}

How to dynamically allocate a 2d array and why?

For my assignment one of the things I have to do in my program is dynamically allocate a 2D array.
I can't figure out how to do it or why.
This is what I have now.
size = atoi(argv[1]);
int Pond[size][size];
int i, j;
for(i = 0; i < size; i ++){
for(j = 0; j < size; j++){
Pond[i][j]=0;
}
}
I found a answer to do it this way but I can't figure out how to access each column or row.
int **Pond;
Pond = (int**)malloc(size * sizeof(int*));
for (i = 0; i < size; i++) {
Pond[i] = (int *) malloc(size * sizeof(int));
Correct use of C's powerful array type syntax looks like this:
int (*Pond)[size] = malloc(size * sizeof(*Pond));
That's it for the allocation. After that, the elements in Pond can simply be accessed like this:
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
Pond[y][x] = 0;
}
}
And of course the deallocation:
free(Pond);
It doesn't get simpler.
The [] operator works on pointers pretty much the same way it works on array expressions, so you'd use Pond[i][j] to access a particular element regardless of how you allocate (unless you allocated it as a 1D array as dom0 shows).
If the number of rows and columns are known at compile time, this is the easiest:
#define M ... // rows
#define N ... // columns
int (*Pond)[N] = malloc ( sizeof *Pond * M);
...
Pond[i][j] = x;
...
free( Pond );
The type of the variable Pond is "pointer to N-element array of int". The type of the expression *Pond is "N-element array of int". So sizeof *Pond gives us the number of bytes in N-element array of int; we multiply this by M to get the total number of bytes required for the array.
Since a[i] is evaluated as *(a + i), the [] operator works the same way on a pointer expression as it does on an array expression1; that is, you could use Pond[i][j] here as you would for a regular 2D array.
If the number of rows and columns are not known until run time, but you're using a C99 compiler or a C2011 compiler that supports variable length arrays, it's pretty much the same:
size_t n, m;
/**
* get values of n and m
*/
int (*Pond)[n] = malloc( sizeof *Pond * m );
...
Pond[i][j] = x;
...
free( Pond );
Same deal as above, it's just that m and n aren't known until runtime. In both of these cases, the dynamically-allocated arrays are contiguous (all rows are adjacent in memory).
+---+
Pond: | | ---+
+---+ |
... |
+---+ |
Pond[0][0]: | | <--+
+---+
Pond[0][1]: | |
+---+
...
+---+
Pond[0][n-1]: | |
+---+
Pond[1][0]: | |
+---+
Pond[1][1]: | |
+---+
...
+---+
Pond[m-1][0]: | |
+---+
Pond[m-1][1]: | |
+---+
...
+---+
Pond[m-1][n-1]: | |
+---+
If the number of rows and columns aren't known until runtime, and you're using a compiler that does not support VLAs, you have two choices depending on whether you want the arrays to be contiguous or not.
If the array doesn't have to be contiguous, you can use a two-step allocation approach:
size_t n, m;
/**
* get values for n and m
*/
int **Pond = malloc( sizeof *Pond * m ); // allocate m rows of pointer to int
if ( Pond )
{
for ( size_t i = 0; i < m; i++ )
{
Pond[i] = malloc( sizeof *Pond[i] * n ); // allocate n columns of int for each row
}
}
In this case, Pond is a pointer to pointer to int; it will wind up pointing to what is effectively a 1D array of pointers to int; each of those pointers will point to a 1D array of int, sort of like the following:
+---+
Pond: | | ---+
+---+ |
|
+------+
|
V
+---+
Pond[0]: | | ------------+
+---+ |
Pond[1]: | | ---------+ |
+---+ | |
Pond[2]: | | | |
+---+ | |
... | |
+---+ | |
Pond[m-1]: | | | |
+---+ | |
| |
+---+ | |
Pond[0][0]: | | <--------|--+
+---+ |
Pond[0][1]: | | |
+---+ |
... |
+---+ |
Pond[0][n-1]: | | |
+---+ |
|
+---+ |
Pond[1][0]: | | <--------+
+---+
Pond[1][1]: | |
+---+
...
+---+
Pond[1][n-1]: | |
+---+
But because Pond[i][j] is evaluated as *(*(Pond + i) + j), it all still works.
Note that since this was a two-step allocation process, deallocation also requires two steps:
for ( size_t i = 0; i < m; i++ )
free( Pond[i] );
free( Pond );
If the array does need to be contiguous, then you'll have to allocate the memory as a 1D array and compute your indexes manually:
int *Pond = malloc( sizeof *Pond * m * n );
...
Pond[ i * m + j ] = x;
...
free( Pond );
1. Under most circumstances, an array expression will be converted or "decay" to a pointer expression, so the subscript is actually working on a pointer expression either way.

Rotate multi-dimension pointer

If I have a multidimension pointer representation of a grid like so
char **p;
int w; // width (i.e. number of columns)
int h; // height (i.e. number of rows)
How do I go about creating a copy that is rotated by 90 degrees clockwise for NxM grid?
I've tried mallocing the height as the new width, and width as new height then transposing the values. Then I was going to finish by reversing the values of the row but I haven't managed to do this.
Actual transposition is moderately painful: you have to move every element from "where it is now" to "where it should be in the transposition". If you really do have a pointer p pointing to the first of M pointers, and each of those M pointers points to the first of N chars (used as if it's an array of size M of arrays of size N of chars):
+---+ +---+---+---+---+
p ---> | * | ----> | a | b | c | d |
+---+ +---+---+---+---+
| * | --
+---+ \ +---+---+---+---+
| * | -----------> | i | j | k | l |
+---+ \ +---+---+---+---+
\
\ +---+---+---+---+
--> | e | f | g | h |
+---+---+---+---+
then you need a new pointer (which I will call q) pointing to the first of N pointers, each of which points to the first of M chars (note: this is a different transposition than you asked for):
+---+ +---+---+---+
q ---> | * | -----> | a | e | i |
+---+ +---+---+---+
| * | --
+---+ \
| * |etc \ +---+---+---+
+---+ ---> | b | f | j |
| * |etc +---+---+---+
+---+
However, if you can live with relatively annoying subscript-writing and any cache miss effects on your runtime, you can simply access p[i][j] as p[j][i] or p[N-1-j][i], etc., to "pretend" that things are transposed. This might be easiest with some macros:
#define ORIENTATION_A(p, M, N, i, j) ((p)[i][j])
#define ORIENTATION_B(p, M, N, i, j) ((p)[(N)-1-(j)][i])
/* etc */
(note: none of the above is tested).
When using type char **, since the fixed-size solution is already posted I thought I would chime in with a dynamic, \0 terminated solution that works with various-sized arrays. If it is possible to terminate the arrays h and w can be omitted. This function can figure out the h and w. Of course it may be changed to support h and w, but the powers that be would rather I get back to work funding their empire rather than providing free help.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
/* rotate_array
w h
**p _______ **q ___
|A B C D|\0 ===> |E A|\0
h |E F G H|\0 ==> |F B|\0 w
NULL----- |G C|\0
|H D|\0
NULL-
*/
char **rotate_array(char **p) {
int w,h,hh;
char **q;
for (w=0;p[0][w];w++);
for (hh=0;p[hh];hh++);
if (!(q = malloc(w * sizeof q))) {
perror ("malloc");
exit (1);
} fprintf (stderr,"made it\n");
for (w=0;p[0][w];w++) {
if (!(q[w] = malloc(hh))) {
perror ("malloc");
exit (1);
} for (h=0;h<hh;h++) {
q[w][hh-h-1] = p[h][w];
} q[w][h]='\0';
} q[w]=NULL;
return q;
} void free_array(char **p) {
int h;
for (h=0;p[h];h++) {
free (p[h]);
} free (p);
}
// main
int main (int argc, char **argv) {
int h;
char *p[3]={"ABCD","EFGH",NULL};
char **q;
for (h=0;p[h];h++) {
printf ("%s\n",p[h]);
} printf ("\n");
q = rotate_array (p);
for (h=0;q[h];h++) {
printf ("%s\n",q[h]);
} free_array (q);
return 0;
}

Resources