How can an address be same as a value? - c

Here is a sample code. I believe array is an address while *array is the value
int array[7][7];
array == *array
But I found out array same as *array. How is it?

Here
int arr[7][7];
arr is two dimensional array containing 7 one dimensional array & each one dimensional array contains 7 elements. It looks like
arr[0][0] arr[0][1] arr[0][2] arr[0][3] arr[0][4] arr[0][5] arr[0][6] arr[0][7]
| | | | | | | | | ....|
---------------------------------------------------------------------- -----
(0x100) | |
arr[0] (0x100) arr[1] ... arr[6]
| |
-----------------------------------------------
|
arr(0x100) -assume base address is 0x100
arr, arr[0] and address of arr[0][0] all results in same i.e arr and *arr results in same address.

You can't have a value without a type.
123456789 just like that is nothing; you need to know if it's an integer, a double, a pointer, ...
So, I like to think of it as the pair (value, type).
And that value could be (123456789, int), or (123456789, double), or (123456789, char*), ... which are all different pairs (with the same value).
In your case you have (<address>, char(*)[7]) not the same as (<address>, char*)

An element of a multidimensional array is an array, which in many cases decays to a pointer to its first element.
So, in both cases you have a pointer to the same location in memory.
As of C, they aren't technically the same, because they point to differents objects, but because those objects have the same address, and because most implementations store all pointers in the same format, they happen to evaluate equal.

Related

How does this piece of code determine array size without using sizeof( )?

Going through some C interview questions, I've found a question stating "How to find the size of an array in C without using the sizeof operator?", with the following solution. It works, but I cannot understand why.
#include <stdio.h>
int main() {
int a[] = {100, 200, 300, 400, 500};
int size = 0;
size = *(&a + 1) - a;
printf("%d\n", size);
return 0;
}
As expected, it returns 5.
edit: people pointed out this answer, but the syntax does differ a bit, i.e. the indexing method
size = (&arr)[1] - arr;
so I believe both questions are valid and have a slightly different approach to the problem. Thank you all for the immense help and thorough explanation!
When you add 1 to a pointer, the result is the location of the next object in a sequence of objects of the pointed-to type (i.e., an array). If p points to an int object, then p + 1 will point to the next int in a sequence. If p points to a 5-element array of int (in this case, the expression &a), then p + 1 will point to the next 5-element array of int in a sequence.
Subtracting two pointers (provided they both point into the same array object, or one is pointing one past the last element of the array) yields the number of objects (array elements) between those two pointers.
The expression &a yields the address of a, and has the type int (*)[5] (pointer to 5-element array of int). The expression &a + 1 yields the address of the next 5-element array of int following a, and also has the type int (*)[5]. The expression *(&a + 1) dereferences the result of &a + 1, such that it yields the address of the first int following the last element of a, and has type int [5], which in this context "decays" to an expression of type int *.
Similarly, the expression a "decays" to a pointer to the first element of the array and has type int *.
A picture may help:
int [5] int (*)[5] int int *
+---+ +---+
| | <- &a | | <- a
| - | +---+
| | | | <- a + 1
| - | +---+
| | | |
| - | +---+
| | | |
| - | +---+
| | | |
+---+ +---+
| | <- &a + 1 | | <- *(&a + 1)
| - | +---+
| | | |
| - | +---+
| | | |
| - | +---+
| | | |
| - | +---+
| | | |
+---+ +---+
This is two views of the same storage - on the left, we're viewing it as a sequence of 5-element arrays of int, while on the right, we're viewing it as a sequence of int. I also show the various expressions and their types.
Be aware, the expression *(&a + 1) results in undefined behavior:
...
If the result points one past the last element of the array object, it
shall not be used as the operand of a unary * operator that is evaluated.
C 2011 Online Draft, 6.5.6/9
This line is of most importance:
size = *(&a + 1) - a;
As you can see, it first takes the address of a and adds one to it. Then, it dereferences that pointer and subtracts the original value of a from it.
Pointer arithmetic in C causes this to return the number of elements in the array, or 5. Adding one and &a is a pointer to the next array of 5 ints after a. After that, this code dereferences the resulting pointer and subtracts a (an array type that has decayed to a pointer) from that, giving the number of elements in the array.
Details on how pointer arithmetic works:
Say you have a pointer xyz that points to an int type and contains the value (int *)160. When you subtract any number from xyz, C specifies that the actual amount subtracted from xyz is that number times the size of the type that it points to. For example, if you subtracted 5 from xyz, the value of xyz resulting would be xyz - (sizeof(*xyz) * 5) if pointer arithmetic didn't apply.
As a is an array of 5 int types, the resulting value will be 5. However, this will not work with a pointer, only with an array. If you try this with a pointer, the result will always be 1.
Here's a little example that shows the addresses and how this is undefined. The the left-hand side shows the addresses:
a + 0 | [a[0]] | &a points to this
a + 1 | [a[1]]
a + 2 | [a[2]]
a + 3 | [a[3]]
a + 4 | [a[4]] | end of array
a + 5 | [a[5]] | &a+1 points to this; accessing past array when dereferenced
This means that the code is subtracting a from &a[5] (or a+5), giving 5.
Note that this is undefined behavior, and should not be used under any circumstances. Do not expect the behavior of this to be consistent across all platforms, and do not use it in production programs.
Hmm, I suspect this is something that would not have worked back in the early days of C. It is clever though.
Taking the steps one at a time:
&a gets a pointer to an object of type int[5]
+1 gets the next such object assuming there is an array of those
* effectively converts that address into type pointer to int
-a subtracts the two int pointers, returning the count of int instances between them.
I'm not sure it is completely legal (in this I mean language-lawyer legal - not will it work in practice), given some of the type operations going on. For example you are only "allowed" to subtract two pointers when they point to elements in the same array. *(&a+1) was synthesised by accessing another array, albeit a parent array, so is not actually a pointer into the same array as a.
Also, while you are allowed to synthesise a pointer past the last element of an array, and you can treat any object as an array of 1 element, the operation of dereferencing (*) is not "allowed" on this synthesised pointer, even though it has no behaviour in this case!
I suspect that in the early days of C (K&R syntax, anyone?), an array decayed into a pointer much more quickly, so the *(&a+1) might only return the address of the next pointer of type int**. The more rigorous definitions of modern C++ definitely allow the pointer to array type to exist and know the array size, and probably the C standards have followed suit. All C function code only takes pointers as arguments, so the technical visible difference is minimal. But I am only guessing here.
This sort of detailed legality question usually applies to a C interpreter, or a lint type tool, rather than the compiled code. An interpretter might implement a 2D array as an array of pointers to arrays, because there is one less runtime feature to implement, in which case dereferencing the +1 would be fatal, and even if it worked would give the wrong answer.
Another possible weakness may be that the C compiler might align the outer array. Imagine if this was an array of 5 chars (char arr[5]), when the program performs &a+1 it is invoking "array of array" behaviour. The compiler might decide that an array of array of 5 chars (char arr[][5]) is actually generated as an array of array of 8 chars (char arr[][8]), so that the outer array aligns nicely. The code we are discussing would now report the array size as 8, not 5. I'm not saying a particular compiler would definitely do this, but it might.

What is a free pointer in C?

I learnt that there are two ways of declaring an array in C:
int array[] = {1,2,3};
and:
int* arr = malloc(3*sizeof(int));
Why is arr called a free pointer ? And why can't I change the address contained in array while I can do it with array ?
As said in comments, you learned something incorrect, from a bad source.
In the second case, arr is not an array, it's a pointer. A pointer that (if the allocation succeeds) happens to contain the address of a block of memory that can hold three ints, but that's not an array.
This confusion probably comes from the fact that arrays "decay" to pointers in some contexts, but that does not make them equivalent.
Let's look at how the two objects are laid out in memory:
+---+
array: | 1 | array[0]
+---+
| 2 | array[1]
+---+
| 3 | array[2]
+---+
+---+ +---+
arr: | | ---------> | ? | arr[0]
+---+ +---+
| ? | arr[1]
+---+
| ? | arr[2]
+---+
So, one immediate difference - there is no array object that is separate from the array elements themselves, whereas arr is a separate object from the array elements. Only array is an actual array as far as C is concerned - arr is just a pointer to a single object, which may be the first element of a sequence of objects or not.
This is why you can assign a new address value to arr, but not to array - in the second case, there's nothing to assign the new address value to. It's like trying to change the address of a scalar variable - you can't do it, because the operation doesn't make any sense.
It also means that the address of array[0] is the same as the address of array. The expressions &array[0], array, and &array will all yield the same address value, although the types of the expressions will be different (int *, int *, and int (*)[3], respectively). By contrast, the address of arr is not the same as the address of arr[0]; the expressions arr and &arr[0] will yield the same value, but &arr will not, and its type will be int ** instead of int (*)[3].

Different Pointer Arithmetic Results when Taking Address of Array

Program:
#include<stdio.h>
int main(void) {
int x[4];
printf("%p\n", x);
printf("%p\n", x + 1);
printf("%p\n", &x);
printf("%p\n", &x + 1);
}
Output:
$ ./a.out
0xbff93510
0xbff93514
0xbff93510
0xbff93520
$
I expect that the following is the output of the above program. For example:
x // 0x100
x+1 // 0x104 Because x is an integer array
&x // 0x100 Address of array
&x+1 // 0x104
But the output of the last statement is different from whast I expected. &x is also the address of the array. So incrementing 1 on this
will print the address incremented by 4. But &x+1 gives the address incremented by 10. Why?
x -> Points to the first element of the array.
&x ->Points to the entire array.
Stumbled upon a descriptive explanation here: http://arjunsreedharan.org/post/69303442896/the-difference-between-arr-and-arr-how-to-find
SO link: Why is arr and &arr the same?
In case 4 you get 0x100 + sizeof x and sizeof x is 4 * sizeof int = 4 * 4 = 16 = 0x10.
(On your system, sizeof int is 4).
An easy thumbrule to evaluate this is:
Any pointer on increment points to the next memory location of its base type.
The base type of &x here is int (*p)[4] which is a pointer to array of 4 integers.
So the next pointer of this type will point to 16 bytes away (assuming int to be 4 bytes) from the original array.
Even though x and &x evaluate to the same pointer value, they are different types. Type of x after it decays to a pointer is int* whereas type of &x is int (*)[4].
sizeof(x) is sizeof(int)*4.
Hence the numerical difference between &x and &x + 1 is sizeof(int)*4.
It can be better visualized using a 2D array. Let's say you have:
int array[2][4];
The memory layout for array is:
array
|
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
array[0] array[1]
| |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
If you use a pointer to such an array,
int (*ptr)[4] = array;
and look at the memory through the pointer, it looks like:
ptr ptr+1
| |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
As you can see, the difference between ptr and ptr+1 is sizeof(int)*4. That analogy applies to the difference between &x and &x + 1 in your code.
Believe it or not, the behaviour of your program is undefined!
&x + 1 is actually pointing to just beyond the array, as #i486's answer cleverly points out. You don't own that memory. Even attempting to assign a pointer to it is undefined behaviour, let alone attempting to dereference it.

Why won't *num show the zeroth element value?

In this code:
#include<stdio.h>
int main()
{
int num[2] = {20, 30};
printf("%d", num);
printf("%d", &num[0]);
return 0;
}
As far as I know, both the printf statement will print the address of the first element in num because in the first statement, num is a pointer to an int.
But if num is a pointer, then it should also have any address but on printing its address (with printf("%d", &num)), it's showing the address of the first element.
In a 2-D array the whole thing becomes confusing too:
#include<stdio.h>
int main(void)
{
int num[ ] [2]={20,30,40,50};
printf("%d",*num);
return 0;
}
This program is printing the address of zeroth element that is the address of num[0][0]. But why does it do this? Why isn't it printing the value stored in it, since they all have same address(num,num[0] and num[0][0])?
First things first; array variables are not pointers; they do not store an address to anything.
For a declaration such as
T a[N];
memory will be laid out as
+---+
a[0]: | |
+---+
a[1]: | |
+---+
...
+---+
a[N-1]: | |
+---+
For a 2D MxN array, it will look like
+---+
a[0][0]: | |
+---+
a[0][1]: | |
+---+
...
+---+
a[0][N-1]: | |
+---+
a[1][0]: | |
+---+
a[1][1]: | |
+---+
...
+---+
a[M-1][N-1]: | |
+---+
The pattern should be obvious for 3D and higher arrays.
As you can see, no storage is set aside for a separate variable a that contains the address of the first element; instead, there is a rule in the C language that an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T" and the value of the expression will be the address of the first element of the array, except when the array expression is one of the following:
an operand of the sizeof operator
an operand of the unary & operator
an operand of the _Alignof operator (C99 and later)
a string literal used to initialize an array in a declaration
So given the declaration
T a[N];
all of the following are true:
Expression Type Decays to Value
---------- ---- --------- -----
a T [N] T * address of first element, &a[0]
*a T n/a value stored in first element
&a T (*)[N] n/a address of the array, which is
the same as the address of the
first element of the array
a[i] T n/a value stored in the i'th element
&a[i] T * n/a address of the i'th element
sizeof a size_t n/a total number of bytes used by the
array
sizeof *a size_t n/a total number of bytes used by the
first element of the array
sizeof &a size_t n/a total number of bytes used by a
pointer to the array
The expression a has type "N-element array of T"; it is not the operand of the unary & or sizeof operators, so it is converted to a pointer to the first element of the array, amd its value is the address of that element.
The expression &a has type "pointer to N-element array of T"; since a is an operand of the unary & operator, the conversion rule above isn't applied (which is why the expression has type T (*)[N] instead of T **). However, since the address of the array is the same as the address of the first element of the array, it yields the same value as the expression a.
The expression &a[0] has type "pointer to T", and explicitly points to the first element of the array. Again, this value will be the same as the previous two expressions.
For a 2D array
T a[M][N];
all of the following are true:
Expression Type Decays to Value
---------- ---- --------- -----
a T [M][N] T (*)[N] address of first subarray, a[0]
*a T [N] T * address pf first subarray, a[0]
&a T (*)[M][N] n/a address of the array, which is
the same as the address of the
first subarray, which is the same
as the address of the first element
of the first subarray.
a[i] T [N] T * address of first element of i'th
subarray
*a[i] T n/a value of first element of i'th subarray
&a[i] T (*)[N] n/a address of the i'th subarray
sizeof a size_t n/a total number of bytes used by the
array
sizeof *a size_t n/a total number of bytes used by the
first subarray
sizeof &a size_t n/a total number of bytes used by a
pointer to the array
Final note: to print out pointer values, use the %p conversion specifier and cast the argument to (void *) (this is the pretty much the only time it's considered proper to explicitly cast a pointer to void *):
printf( " &a yields %p\n", (void *) &a );
printf( " a yields %p\n", (void *) a );
printf( "&a[0] yields %p\n", (void *) &a[0] );
Edit
To answer a question in the comments:
num,num[] and num[][] are all different thing. There types are different.Here num decays and became pointer to a pointer and num[] decays and became pointer to int and num[][] is a int. Right?
Not quite.
Assuming a declaration like
int arr[10][10];
then the expression arr will decay to type int (*)[10] (pointer to 10-element array of int), not int **; refer to the table above again. Otherwise you're right; arr[i] will decay to type int *, and arr[i][j] will have type int.
An expression of type "N-element array of T" decays to type "pointer to T"; if T is an array type, then the result is "pointer to array", not "pointer to pointer".
In the second example, num is a 2 dimensional array, or say an array of array. It's true that *num is its first element, but this first element is an array itself.
To get num[0][0], you need **num.
printf("%d\n", **num);
Look how an array looks like:
int num[ ] [2]={20,30,40,50};
is better written as
int num[][2]={{20,30},{40,50}};
It is an array with 2 elements. Those 2 elements are, again, arrays with 2 ints.
In memory, they look like
20 30 40 50
but the difference is that num refers to the whole array, num[0] to the first "part- array" and num[0][0] to the first element of the first array.
They have the same address (because they start at the same place), but they have a different type.
That is, the address is not the only important thing with a pointer, the type is important as well.
Arrays are not pointers actually, though they tend to act in a bit similar way, but not always.
Say you have this array and a pointer:
int a[] = {1, 2, 3};
int i = 19;
int *ptr = &i;
Now here a is equal to &a, but the same is not true, for pointers (ptr is not equal to &ptr).
Now coming to the question:
Consider a single dimensional array:
int arr[] = {11, 19, 5, 9};
Here, this array elements are stored in contiguous memory locations. Say, with starting address 0:
---------------------
| 11 | 19 | 5 | 9 |
---------------------
0 4 8 12 16
Now when you write name of the array, arr (for this example), you will get the starting address of the 1st element. Though if you write &arr, then you get the starting address of the whole block(this includes all the elements of the array). Now when you write *arr, you actually get the value inside the 1st element of this array.
Now consider this 2-dimensional array arr[][4] = {{11, 19, 5, 9}, {5, 9, 11, 19}}:
0 4 8 12 16 -> These are memory addresses
---------------------
| 11 | 19 | 5 | 9 | ----> These values represent the values inside each index
---------------------
| 5 | 9 | 11 | 19 |
---------------------
16 20 24 28 32
Here, when you write the name of the array, as arr, what you get is the address of the 1st element of this array, which in this case will be address of this 0th index:
0 16 32
----------------------------------------------
| 0<sup>th</sup> index | 1<sup>st</sup> index |
----------------------------------------------
Now when you do &arr, here what you get is the base address for whole of the block, i.e. base address of this:
0 4 8 12 16
---------------------
| 11 | 19 | 5 | 9 |
---------------------
| 5 | 9 | 11 | 19 |
---------------------
16 20 24 28 32
Now, if you do *arr, in 1-dimensional array it gives you the value inside the 1st element, though in 2-dimensional array, the value inside each index is actually one 1-dimensional array, hence you will get the address of this array:
0 4 8 12 16
---------------------
| 11 | 19 | 5 | 9 |
---------------------
Now if you do **arr, that is when you will actually get the value inside the 1st element, which is 11.
I hope it clears some doubts :-)
EDIT 1:
As brought to my attendtion, by fellow user, it seems there is a bit of a confusion somewhere, though I have explained in detail what is meant by what thingy. But just to justify, for this statement:
Now here __a is equal to &a__, but the same is not true, for pointers (__ptr is not equal to &ptr__).
The types of both a and &a will be different, as already stated, in the answer. If one performs pointer arithmetics, one will able to know that. Try performing a + 1 and &a + 1, how they both react to pointer arithmetics will surely give a good idea.
Considering a 1-dimensional array:
int arr[] = {11, 19, 5, 9};
---------------------
| 11 | 19 | 5 | 9 |
---------------------
0 4 8 12 16
We cannot do a++, though for a pointer:
int i = 4;
int *ptr = &i;
we can perform ptr++, this will make ptr point to the next memory location.
I think it result means that the array not really a pointer, but it is converted to a pointer in some contexts that is expected a pointer, like pass to a function that expect a pointer argument.
see this code:
void test(int* num) {
printf("test\n");
printf("%p\n",num);
printf("%p\n",&num);
printf("%p\n",&num[0]);
}
int main(){
int num[2]={20,30};
test(num);
printf("main\n");
printf("%p\n",num);
printf("%p\n",&num);
printf("%p\n",&num[0]);
//other();
return 0;
}
The output is:
test
0x7fff7a422300
0x7fff7a4222e8 //LOOK THIS! Is diferent from main!
0x7fff7a422300
main
0x7fff7a422300
0x7fff7a422300
0x7fff7a422300

Array of pointers to array of int

After a lot of fight I figured out in a declaration like int A[2][3], A is of a type compatible with int(*)[3] . My understanding is A can be used to point to the first three elements and A + 1 to the next three.
Is there any way I can declare an array of pointers to array.
ptr_array
+----+ +----+----+----+
| | ----> | | | |
| | | 24 | 25 | 26 |
+----+ +----+----+----+
| | | 44 | 45 | 46 |
| | ----> | | | |
+----+ +----+----+----+
Array of pointers two dimensional array of three integers
to array of 3
How do I declare ptr_array, so that
ptr_array[0] = A;
and
ptr_array[1] = A + 1;
Multidimensional arrays in C are arrays of arrays. The elements of an n-dimensional array are (n-1) dimensional arrays. A[0], for example, is an int [3].
A: |24|25|26|44|45|46|
A[0]: |24|25|26|
A[1]: |44|45|46|
In certain contexts, an array is converted to a pointer to the first element of the array, but the array is not itself a pointer.
From the C standard, § 6.5.2.1-3:
3 Successive subscript operators designate an element of a multidimensional array object. If E is an n-dimensional array (n≥2) with dimensions i× j×...×k, then E (used as other than an lvalue) is converted to a pointer to an (n − 1)-dimensional array with dimensions j × . . . × k. If the unary * operator is applied to this pointer explicitly, or implicitly as a result of subscripting, the result is the pointed-to (n − 1)-dimensional array, which itself is converted into a pointer if used as other than an lvalue. It follows from this that arrays are stored in row-major order (last subscript varies fastest).
4 EXAMPLE Consider the array object defined by the declaration
int x[3][5];
Here x is a 3 × 5 array of ints; more precisely, x is an array of three element objects, each of which is an array of five ints. In the expression x[i], which is equivalent to (*((x)+(i))), x is first converted to a pointer to the initial array of five ints. Then i is adjusted according to the type of x, which conceptually entails multiplying i by the size of the object to which the pointer points, namely an array of five int objects. The results are added and indirection is applied to yield an array of five ints. When used in the expression x[i][j], that array is in turn converted to a pointer to the first of the ints, so x[i][j] yields an int.
To create a ptr_array as diagrammed:
int (*ptr_array[2])[3]
ptr_array[0] = A;
ptr_array[1] = A+1;
// or:
ptr_array[0] = &A[0];
ptr_array[1] = &A[1];
// or even:
ptr_array[0] = (int(*)[3])A[0];
ptr_array[1] = (int(*)[3])A[1];
// though this last shouldn't be used in production code
Here's how to work out the declaration. From the diagram, ptr_array is an array of size 2.
... ptr_array[2] ...
The elements of the array are pointers
*ptr_array[2]
to arrays of size 3
(*ptr_array[2])[3]
of ints
int (*ptr_array[2])[3]
If you're ever not certain how to declare something like this, you can use cdecl:
cdecl> declare ptr_array as array 2 of pointer to array 3 of int
int (*ptr_array[2])[3]
You can install a command line version of cdecl (if not already installed) on your development computer. The exact method depends on the platform. Check the documentation and web at large.
In a declaration like int A[2][3], A is of a pointer to an array of 3 which means A is of type int(*)[3]
No. A is an array, not a pointer. It is of type int [2][3].
How do I declare ptr_array, so that
ptr_array[0] = A;
and
ptr_array[1] = A + 1;
If by A+1 you mean "the second length-3 array", then you simply need to do this:
int (*ptr_array)[3] = A;
An array decays to become a pointer to its first element in most situations. I suggest reading the C FAQ on arrays and pointers: http://c-faq.com/aryptr/index.html.
Yes. You can declare an array to be of anything you like.
Your declaration
int A[2][3];
defines a two-dimensional array of ints, of size 2x3. A[0] is a pointer to the start of an array of 3 ints, as is A[1]. A[0][0] is the first element in the first array. A[1][2] is the last element of the last array.
A[2][3] is more an array than a pointer. There are only some cases you can consider array as pointers. A is an array to 6 integers. A is of type integer array.
You can declare ptr_array[0] as A[0] and ptr_array as A[1].

Resources