Click here to Skip to main content
15,886,919 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am struggling with understanding how this works:

C
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int rows = 2;
    int columns = 5;
    int **matrix = (int **) malloc(rows * sizeof(int *));
    matrix[0] = (int *) malloc(rows * columns * sizeof(int));
    for (int i = 1; i < rows; i++)
    {
        matrix[i] = matrix[0] + i * columns;
        //printf("%p", *matrix[i]);
    }
     for (int i = 0; i < rows; i++)
    {
      
        printf("Indeks : %d, Address of (matrix) : %p\n", i, matrix+i);
        printf("Indeks : %d, Address of (*matrix) : %p\n", i, *(matrix+i));
    }
    
    return 0;
}


The results are like here:

https://i.postimg.cc/FRZbkLLR/obraz-2023-10-18-050416732.png[^]

Indeks : 0, Address of (matrix) : 0x55eff083e2a0
Indeks : 0, Address of (*matrix) : 0x55eff083e2c0
Indeks : 1, Address of (matrix) : 0x55eff083e2a8
Indeks : 1, Address of (*matrix) : 0x55eff083e2d4 


From tutorial like here:

It shows that the addres of matrix should change every 4 bytes but it changes every 8 bytes in my code and it uses malloc. But for the *matrix if changes every 4 bytes and it is also malloc "array", so why in one malloc it changes every 8 bytes and in other 4 bytes they are both int and int value takes 4 bytes.

So how does he know that when I write matrix + 1, he know that I want to move 4 bytes to another number which is located in the picture 604 this is another number. Like how does he convert it into 8 bytes or 4 bytes when both mallocs are pointers (I heard that pointer takes 8 bytes but (int*) malloc is also a pointer, but it takes 4 bytes not 8).

Or another example with chars.

C
#include <stdio.h>

int main()
{ 
    char* arr[3] = { "geek", "Geeks", "Geeksfor" };
 
    for (int i = 0; i < 3; i++) {
        printf("Indeks : %d, Address of (arr) : %p\n",i , *(arr+i));
        printf("Indeks : %d, Address of (&arr) : %p\n",i , &arr[i]);
    }
 
    return 0;
}


The results:

Indeks : 0, Address of (arr) : 0x55ae7f302008
Indeks : 0, Address of (&arr) : 0x7fff60e25ef0
Indeks : 1, Address of (arr) : 0x55ae7f30200d
Indeks : 1, Address of (&arr) : 0x7fff60e25ef8
Indeks : 2, Address of (arr) : 0x55ae7f302013
Indeks : 2, Address of (&arr) : 0x7fff60e25f00


Now here also 4 bytes difference or more when looking at address arr (char has only 1 byte when there are 4 letters it takes 4 bytes logical). But the &arr has 8 bytes. Why?

It doesn't make sense when I write &arr + 1 knowing that char is 1 byte then why it does it go every 8 bytes ?
Same goes with the first example. I am struggling to understand when I type *matrix + 1, it will go 4 bytes but when I type matrix + 1, it will go 8 bytes how does he know when both malloc addreses are pointers which means they should be 8 bytes adresses

PS.
I'm just very confused how these bytes work and how does he know that when I write matrix + 1, it goes by 4 bytes. When I have char * arr it is like pointer to a pointer because address of arr is a pointer to the inside of arr which is also a pointer and this pointer points to the address of a value like "G". So two pointers but one is 1 byte per character, and another pointer is 1 byte ahead but the size of pointers should be 8 bytes ... I don't get it at all how it works and how the arithmetics works there.

What I have tried:

I tried reading about arithmetics and I understood something about sizeof(int) or sizeof(int *) but I don't get it at all. Same goes with that pointer should be either 4 bytes or 8 bytes, but in my case, it is 1 byte per character for pointer ... or maybe I don't understand the notation such as matrix + i, but I understand that the address of matrix is shifted by + i with sizeof. The difference between two addresses of matrix is 8 bytes so +1 is shifting by 8 bytes but when I write *(matrix+i), the difference between *(matrix+0) and *(matrix+1) is only 5 bytes (because 4 characters + \0 character) the other *(matrix+2) is 6 bytes difference.
Posted
Updated 19-Oct-23 7:43am
v4

I partially already mentioned answer to this in your previous question.
Indeks : 0, Address of (matrix) : 0x55eff083e2a0
Indeks : 0, Address of (*matrix) : 0x55eff083e2c0
Indeks : 1, Address of (matrix) : 0x55eff083e2a8
Indeks : 1, Address of (*matrix) : 0x55eff083e2d4

0x55eff083e2a8 - 0x55eff083e2a0 = 0x08
0x55eff083e2d4 - 0x55eff083e2c0 = 0x08

you can check the size of the pointer next way:
printf("%d\n",sizeof(int*));
printf("%d\n",sizeof(int**));

In your next example same:

0x7fff60e25f00 - 0x7fff60e25ef8 = 8
0x7fff60e25ef8 - 0x7fff60e25ef0 = 8

The values you are provided as *(arr+1) are invalid - it is not possible to have such address of the pointer type 0x55ae7f302013

More of it you are posting here not the actual results of the program execution as the resulted length of your pointers is 6 bytes: 55 ae 7f 30 20 13 - which is not possible with your print output.
The "0x" prefix is not set on your printf function so it should be: printf("Indeks : %d, Address of (arr) : 0x%p\n",i , *(arr+i)); instead.

So here is the question to you: are you either run the code you are asking about to understand how it work?
 
Share this answer
 
Comments
Member 16116753 18-Oct-23 8:22am    
"So here is the question to you: are you either run the code you are asking about to understand how it work?" Yes.

"0x55eff083e2d4 - 0x55eff083e2c0 = 0x08". I don't get this part. One byte difference is adding hexa 1 to the addres right ? Like 0x55eff083e2d4 + 1 byte is 0x55eff083e2d5 this is one byte difference as I assume so how substracting it you have 8 ? I've got 14 in hexa which is 20 in decimal so it's 20 bytes difference.

"The values you are provided as *(arr+1) are invalid - it is not possible to have such address of the pointer type 0x55ae7f302013". When I turned on again the compiler it showed some errors but showed some values.

I still don't get it how it works ...
So what is *(arr+i), (arr+i) or &arr+i ? Same goes with the second example. Because I get mixed how it works and how it operates.

I've changes a bit the code but it still couldn't work well :

#include <stdio.h>

int main()
{
 
    char* arr[3] = { "geek", "Geeks", "Geeksfor" };
 
    for (int i = 0; i < 3; i++) {
        printf("Indeks : %d, Address of (arr) : %p\n",i , arr+i);
        printf("Indeks : %d, Address of (&arr) : %p\n",i , &arr+i);
    }
 
    return 0;
}


Result :

main.cpp: In function ‘int main()’:
main.cpp:14:22: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   14 |     char* arr[3] = { "geek", "Geeks", "Geeksfor" };
      |                      ^~~~~~
main.cpp:14:30: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   14 |     char* arr[3] = { "geek", "Geeks", "Geeksfor" };
      |                              ^~~~~~~
main.cpp:14:39: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   14 |     char* arr[3] = { "geek", "Geeks", "Geeksfor" };
      |                                       ^~~~~~~~~~
Indeks : 0, Address of (arr) : 0x7fffcac41510
Indeks : 0, Address of (&arr) : 0x7fffcac41510
Indeks : 1, Address of (arr) : 0x7fffcac41518
Indeks : 1, Address of (&arr) : 0x7fffcac41528
Indeks : 2, Address of (arr) : 0x7fffcac41520
Indeks : 2, Address of (&arr) : 0x7fffcac41540


I am so lost because now I see only bytes and I don't get it how it works ...

PS.

Like the picture here : obraz 2023 10 18 050416732 — Postimages[^]

It shows that matrix[0] or *matrix+0 have address 600 and it's next element is shifted by 4 bytes (604) how does he know ? This is a pointer it should shift by 8 bytes. And in my results it shows it is I guess 4 bytes ? I don't know what is what now to be honest I need some help here.
Maxim Kartavenkov 18-Oct-23 9:32am    
0x55eff083e2d4 - 0x55eff083e2c0 yep you right - this is the difference between matrix[1] and matrix[0] so in your example its equals to columns * sizeof(int);

The value of 0x55ae7f302013 seems was not from the code you specify but from some of your experiment.
arr + 1 means arr[1] which is pointer
*(arr + 1) means arr[1][0] which is character
&arr + 1 means arr + sizeof(arr) which has invalid address
Maxim Kartavenkov 18-Oct-23 9:09am    
what you try to get by the &arr + i ?
0x7fffcac41540 - 0x7fffcac41528 = 0x18 which is equals to sizeof(arr);
0x7fffcac41528 - 0x7fffcac41510 = 0x18 - same

0x7fffcac41520 - 0x7fffcac41518 = 0x08
0x7fffcac41518 - 0x7fffcac41510 = 0x08
Member 16116753 18-Oct-23 9:50am    
I am basically confused because char* array is a pointer so I thought that the address of the array is also 8 byte big.

Same goes with matrix. I don't know what is matrix+i, *(matrix + i), &matrix + i. And why when I type *(matrix+0) and *(matrix+1) it is 4 byte difference although it is a pointer I guess. If its a pointer it should always be 8 byte because pointers have 8 bytes. The value is in **(matrix+0) this is the value. And what if I type &(matrix+0) ?

sizeof(arr) I was told it is the same as the size of a type it is assigned to.
What I imagined is let's say I have normal array -> value[2], so the &value[0] is basically the address of that array, and the value[0] is what is has inside. So when I say int *value[2] then I add another pointer but inside of value[0] so now I have two pointers one from the address to the pointer &value[0] -points-> value[0] and this pointer which should be 8 byte big points to the value value[0] -> *value[0]. But I get lost what is what. So when I write value + 1 <==> &value[1], I shift it by 8 bytes ? But when I write value[0][1] then I shift one by 0*8 bytes and another shift is 1*4 bytes ? I wonder why 4 bytes in the second one though ... Like I said it is very confusing for me.
Maxim Kartavenkov 18-Oct-23 10:11am    
In second time you just access second integer value in the array which is 4 bytes long
In your last example each of the pointers in arr point to the address of a fixed char array in memory, allocated by the compiler. So in essence the elements of arr (an array of pointers) are:
0 -> "geek\0"
5 -> "Geeks\0"
11 -> "Geeksfor\0"

But arr is an array of pointers, and you are printing (on the second line) the address of each pointer, which are all 8 bytes long.

[edit]
A diagram might help here:
--------------------------------------------
|g|e|e|k|\0|G|e|e|k|s|\0|G|e|e|k|s|f|o|r|\0|
--------------------------------------------
|0|1|2|3|4 |5|6|7|8|9 ...

So those addresses [ 0, 5, 11 ] are the only valid ones in this diagram. The address of arr[0], arr[1] etc, gives the addresses of the poointers, not what they are pointing to, i.e. those three strings.

[/edit]

[edit seq="2"]
Changing the code to the following, may make the difference in the addresses somewhat clearer:
C++
#include <stdio.h>

int main()
{
 
    char* arr[3] = { "geek", "Geeks", "Geeksfor" };

    for (int i = 0; i < 3; i++) {
        printf("*(arr+%d) : %p\n", i, *(arr+i));
    }
    printf("\n");
    for (int i = 0; i < 3; i++) {
        printf("  arr+%d  : %p\n", i, arr+i);
    }
    printf("\n");
    for (int i = 0; i < 3; i++) {
        printf(" &arr+%d  : %p\n", i, &arr+i);
    }
    printf("\n");
 
    return 0;
}


I have removed the first couple of sentences referring to pointer arithmetic, as they are not relevant to this issue.
[/edit]
 
Share this answer
 
v4
Comments
Member 16116753 18-Oct-23 8:45am    
I get usually mixed in what is the address of the pointer and what is the address of a value.

Isn't *arr a value we want to get right ? so arr is also a pointer to that value *arr. So why arr is random bytes like 5 or 6 etc like you said with "geek\0" that is 5 byte big and "Geeks\0" that is 6 byte big. So the difference between geek and Geeks is 5 byte and not 8 either though arr is a pointer and *arr is a value.

I'll give a better example maybe we have an char* arr[3] not let's make blocks &arr[0] is


char* arr[3]

Address of each element

&arr[0] = 0x7fff60e25ef0 -> [ arr[0] - pointer (it's address 0x55ae7f302008) ] -> [arr[0][0] value of a letter and it's address is passed to the pointer 0x55ae7f302223]

&arr[1] = 0x7fff60e25ef8 -> [ arr[1] - pointer (it's address 0x55ae7f30200D) ] -> [arr[0][1] value of a letter and it's address is passed to the pointer ???]

The problem was that the arr[0] shifted by 5 bytes but it is not a letter it is just a pointer.

Another example :

Normal array :

int value [2]

So :

&value[1] = 0x7fff60e25ef8 -> [ value[1] - value (it's address 0x55ae7f30200D) ]

It is only one pointer which is &value to the element in value[1] that's why I saw that value[1] is equal to *value+1. But it is still a pointer &value[1] so why it shifts only 4 bytes and not 8 ?

I don't know if what I wrote is understandable, because as I said I am so mixed I need some more images or examples from easy to harder because everything is now mixed ...

In the pictures like here : obraz 2023 10 18 050416732 — Postimages[^] it was hard to understand or from websites like : https://www.oreilly.com/library/view/understanding-and-using/9781449344535/ch04.html or https://www.geeksforgeeks.org/pointer-arithmetics-in-c-with-examples/ .

They say that the pointer is 8 byte big but in images it shows that it is shited by 4 bytes. But why now pointer is 4 byte and not 8 ??? It said that pointers are always 8 bytes or 4 bytes. But when I add char it changes into 1 byte so I don't get it.
Richard MacCutchan 18-Oct-23 9:04am    
You are getting confiused between the length of a pointer, and the length of its target. In the array above there are three pointers, and as I said they are allocated at compile time. Since they each point to a character string, it appears that they are variable distances apart. But what you are displaying is the address of the item that the pointer is pointing to. When you print the addresses of the pointers themselves you can clearly see that they are 8 bytes apart.
Member 16116753 18-Oct-23 9:17am    
Yes indeed I am confused. So in other words what am I printing typing *(arr + 1), arr+1 and &arr + 1 ?

Because the arithmetics works how ? arr is always as I know the same address so it always shifts by 8 bytes and shows it's content ?

Like here :

#include <stdio.h>

int main()
{
 
    char* arr[3] = { "geek", "Geeks", "Geeksfor" };
 
    for (int i = 0; i < 3; i++) {
        printf("Indeks : %d, Address of (arr) : %p\n",i , *(arr+i));
        printf("Indeks : %d, Address of (&arr) : %p\n",i , arr+i);
        printf("Indeks : %d, Address of (&arr) : %p\n",i , &arr+i);
    }
 
    return 0;
}


Results :

Indeks : 0, Address of (arr) : 0x5644e043b008
Indeks : 0, Address of (&arr) : 0x7ffd0a7a3e60
Indeks : 0, Address of (&arr) : 0x7ffd0a7a3e60
Indeks : 1, Address of (arr) : 0x5644e043b00d
Indeks : 1, Address of (&arr) : 0x7ffd0a7a3e68
Indeks : 1, Address of (&arr) : 0x7ffd0a7a3e78
Indeks : 2, Address of (arr) : 0x5644e043b013
Indeks : 2, Address of (&arr) : 0x7ffd0a7a3e70
Indeks : 2, Address of (&arr) : 0x7ffd0a7a3e90


Or in my matrix example. What am I showing typing matrix+1 and *(matrix+1) ?

In the image here : obraz 2023 10 18 050416732 — Postimages[^] it shows that *(matrix + 1) is the value inside of 600. So I understand that shifting matrix + 1 I will get 608 ? Because it is 8 byte or is it different shifting because it should be matrix[0][1] the second element in 1st row, But I don't know how to write it in *(matrix+i) notation to have 2 elements And how does it shift.

PS.
I still feel confused when I think about the matrix because *matrix is alocated in malloc that sizeof(int) is 4 and not 8 hmmmm I don't know what is what ...
Richard MacCutchan 18-Oct-23 10:25am    
OK so let us consider what you are actually displaying:
1. printf("Indeks : %d, Address of (arr) : %p\n",i , *(arr+i));
2. printf("Indeks : %d, Address of (&arr) : %p\n",i , arr+i);
3. printf("Indeks : %d, Address of (&arr) : %p\n",i , &arr+i);

The tag arr + i is the address of the pointer at location i in the array arr. So pointer 0, 1 and 2 (3 items).

1. You take the content of arr + i, which is a pointer which points to a string of characters and will be allocated by the compiler. Its actual value has nothing to do with pointer arithmetic, it is purely a random address as allocated by the compiler.

2. You take the actual pointer at arr + i and print its address. And since it is one of three pointers, they will each be 8 bytes distant from their predecessor.

3. You are printing the address of the array itself, plus 0, 1 and 2. And since the array is 3 pointers in size, this address will increase by the size of the array itself.
Member 16116753 18-Oct-23 11:09am    
Okey so what happens with my matrix then ?
In this picture from a website https://www.javatpoint.com/c-pointer-to-pointer It shows that **pp and *p and "a" are used in the example so typing printf("%p",pp) will give me the address of p, typing printf("%p",*pp), the address of "a" and typing printf("%p",**pp), the value of "a".

But how it works in my matrix : https://postimg.cc/8J7fqswQ

when I type printf("%p",matrix) I will get the address 500, when I type printf("%p",*matrix) I get the address of 600 so when I type printf("%p",**matrix) i get the address of a variable I write there not the value so I should write printf("%p",***matrix) ??? Because **malloc is a double pointer and *malloc is a single pointer.

*matrix gets the addres of 600 which is the address of *malloc it is a pointer. So what it contains I have to use **matrix and the value of that address must be ***matrix ???

Weird not gonna lie. Also *malloc is 4 byte not 8 byte even though it is a pointer ... Or am I again mixing stuff because I compared this double pointer to simpler version which is this :

#include<stdio.h>  
void main ()  
{  
    int a = 10;  
    int *p;  
    int **pp;   
    p = &a; // pointer p is pointing to the address of a  
    pp = &p; // pointer pp is a double pointer pointing to the address of pointer p  
    printf("address of a: %x\n",p); // Address of a will be printed   
    printf("address of p: %x\n",pp); // Address of p will be printed  
    printf("value stored at p: %d\n",*p); // value stoted at the address contained by p i.e. 10 will be printed  
    printf("value stored at pp: %d\n",**pp); // value stored at the address contained by the pointer stoyred at pp  
}  


So when pp showed the addres of p then in my example matrix shows the addres of (int **) malloc which is 500, then again *pp shows the addres of a variable in my case *matrix shows the address of (int *) malloc which is 600, and it is not the addres of a value, and lastelly **pp is the value of a, in my example **matrix shows the addres of value stored in 600 ...

Do you maybe know why I am so confused with this ? It's hard to explain but now (int *) malloc has 4 bytes just because why not but it is a pointer to the addres let's say x = 5 so the address of x = 5 lets say 1001 is stored in 600 which is this thing I guess ????

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900