Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is x[0] != x[0][0] != x[0][0][0]?

People also ask

Why is X 0 not possible?

Since the definition x0 = 1 is based upon division, and division by 0 is not possible, we have stated that x is not equal to 0. Actually, the expression 00 (0 to the zero power) is one of several indeterminate expressions in mathematics. It is not possible to assign a value to an indeterminate expression.

Why is 0 0 indeterminate?

Well, any number raised to the power of zero does equal 1 because the base, or the number being raised to any power, gets divided by itself. For example, 30 equals 3/3, which equals 1, but 00 "equals" 0/0, which equals any number, which is why it's indeterminate.

Is it 0 0 or infinity?

In mathematics, expressions like 1/0 are undefined. But the limit of the expression 1/x as x tends to zero is infinity. Similarly, expressions like 0/0 are undefined.

What does X [: I mean in Python?

Meaning of X = X[:, 1] in Python is: X is a dataset or a array. Say Here X have n rows and n columns. so by doing x=x[:,1] we get all the rows in x present at index 1.


x is a pointer to an array of 5 pointers to int.
x[0] is an array of 5 pointers to int.
x[0][0] is a pointer to an int.
x[0][0][0] is an int.

                       x[0]
   Pointer to array  +------+                                 x[0][0][0]         
x -----------------> |      |         Pointer to int           +-------+
               0x500 | 0x100| x[0][0]---------------->   0x100 |  10   |
x is a pointer to    |      |                                  +-------+
an array of 5        +------+                        
pointers to int      |      |         Pointer to int                             
               0x504 | 0x222| x[0][1]---------------->   0x222                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x508 | 0x001| x[0][2]---------------->   0x001                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x50C | 0x123| x[0][3]---------------->   0x123                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x510 | 0x000| x[0][4]---------------->   0x000                    
                     |      |                                             
                     +------+                                             

You can see that

  • x[0] is an array and will converted to pointer to its first element when used in an expression (with some exceptions). Therefore x[0] will give the address of its first element x[0][0] which is 0x500.
  • x[0][0] contains address of an int which is 0x100.
  • x[0][0][0] contains an int value of 10.

So, x[0] is equal to &x[0][0]and therefore, &x[0][0] != x[0][0].
Hence, x[0] != x[0][0] != x[0][0][0].


x[0] != x[0][0] != x[0][0][0]

is, according to your own post,

*(x+0) != *(*(x+0)+0) != *(*(*(x+0)+0)+0)`  

which is simplified

*x != **x != ***x

Why should it be equal?
The first one is the address of some pointer.
The second one is the address of another pointer.
And the third one is some int value.


Here is the memory layout of your pointer:

   +------------------+
x: | address of array |
   +------------------+
            |
            V
            +-----------+-----------+-----------+-----------+-----------+
            | pointer 0 | pointer 1 | pointer 2 | pointer 3 | pointer 4 |
            +-----------+-----------+-----------+-----------+-----------+
                  |
                  V
                  +--------------+
                  | some integer |
                  +--------------+

x[0] yields "address of array",
x[0][0] yields "pointer 0",
x[0][0][0] yields "some integer".

I believe, it should be obvious now, why they are all different.


The above is close enough for basic understanding, which is why I wrote it the way I wrote it. However, as haccks rightly points out, the first line is not 100% precise. So here come all the fine details:

From the definition of the C language, the value of x[0] is the whole array of integer pointers. However, arrays are something you can't really do anything with in C. You always manipulate either their address or their elements, never the entire array as a whole:

  1. You can pass x[0] to the sizeof operator. But that's not really a use of the value, its result depends of the type only.

  2. You can take its address which yields the value of x, i. e. "address of array" with the type int*(*)[5]. In other words: &x[0] <=> &*(x + 0) <=> (x + 0) <=> x

  3. In all other contexts, the value of x[0] will decay into a pointer to the first element in the array. That is, a pointer with the value "address of array" and the type int**. The effect is the same as if you had casted x to a pointer of type int**.

Due to the array-pointer decay in case 3., all uses of x[0] ultimately result in a pointer that points the beginning of the pointer array; the call printf("%p", x[0]) will print the contents of the memory cells labeled as "address of array".


  • x[0] dereferences the outermost pointer (pointer to array of size 5 of pointer to int) and results in an array of size 5 of pointer to int;
  • x[0][0] dereferences the outermost pointer and indexes the array, resulting in a pointer to int;
  • x[0][0][0] dereferences everything, resulting in a concrete value.

By the way, if you ever feel confused by what these kind of declarations mean, use cdecl.


Let consider step by step expressions x[0], x[0][0] and x[0][0][0].

As x is defined the following way

int *(*x)[5];

then expression x[0] is an array of type int *[5]. Take into account that expression x[0] is equivalent to expression *x. That is dereferencing a pointer to an array we get the array itself. Let denote it like y that is we have a declaration

int * y[5];

Expression x[0][0] is equivalent to y[0] and has type int *. Let denote it like z that is we have a declaration

int *z;

expression x[0][0][0] is equivalent to expression y[0][0] that in turn is equivalent to expression z[0] and has type int.

So we have

x[0] has type int *[5]

x[0][0] has type int *

x[0][0][0] has type int

So they are objects of different types and by the way of different sizes.

Run for example

std::cout << sizeof( x[0] ) << std::endl;
std::cout << sizeof( x[0][0] ) << std::endl;
std::cout << sizeof( x[0][0][0] ) << std::endl;

First thing I have to say that

x [ 0 ] = * ( x + 0 ) = * x ;

x [ 0 ] [ 0 ] = * ( * ( x + 0 ) + 0 ) = * * x ;

x [ 0 ] [ 0 ] [ 0 ] = * ( * ( * ( x + 0 ) + 0 ) ) = * * * x ;

So * x ≠ * * x ≠ * * * x

From the following picture all things are clear.

  x[0][0][0]= 2000

  x[0][0]   = 1001

  x[0]      = 10

enter image description here

It is just an example, where value of x[0][0][0]=10

and address of x[0][0][0] is 1001

that address is stored in x[0][0]=1001

and address of x[0][0] is 2000

and that address is stored at x[0]=2000

So x[0][0][0] x[0][0] x[0]

.

EDITINGS

Program 1:

{
int ***x;
x=(int***)malloc(sizeof(int***));
*x=(int**)malloc(sizeof(int**));
**x=(int*)malloc(sizeof(int*));
***x=10;
printf("%d   %d   %d   %d\n",x,*x,**x,***x);
printf("%d   %d   %d   %d   %d",x[0][0][0],x[0][0],x[0],x,&x);
}

Output

142041096 142041112 142041128 10
10 142041128 142041112 142041096 -1076392836

Program 2:

{
int x[1][1][1]={10};
printf("%d   %d   %d   %d \n ",x[0][0][0],x[0][0],x[0],&x);
}

Output

10   -1074058436   -1074058436   -1074058436 

If you were to view the arrays from a real-world perspective, it would appear as thus:

x[0] is a freight container full of crates.
x[0][0] is a single crate, full of shoeboxes, within the freight container.
x[0][0][0] is a single shoebox inside the crate, inside the freight container.

Even if it were the only shoebox in the only crate in the freight container, it is still a shoebox and not a freight container