I am currently learning arrays in C. In the training that I follow, it is marked two things that cause me problems :
- The first is that in the RAM each of the boxes that make up the table follows one another
- The second is that a table is a pointer that points to the first box of the table
Could someone clarify for me about the storage of arrays in RAM and their relationship to pointers?
But when I do this I notice that the addresses do not follow each other :
int arrays[3] = {10, 20, 30};
int i = 0;
for (i=0 ; i < 3 ; i )
{
printf("%d : %d\n", i, &arrays[i]);
}
Result : 0 : 973077712 1 : 973077716 2 : 973077720
And when I do this I notice that array and &array give me the same value which should not be the case for a "classic pointer" :
printf("value of arrays : %d\n", arrays);
printf("value of &arrays : %d\n", &arrays);
Result : value of arrays : 1522530048 value of &arrays : 1522530048
CodePudding user response:
If you have an array of some type T
like
T a[N];
then the difference between the addresses of two adjacent elements of the array are equal to sizeof( T )
. And this output shows that convention provided that in your system sizeof( int )
is equal to 4
.
Result : 0 : 973077712 1 : 973077716 2 : 973077720
That is as pointed out above sizeof( int )
in the used system is equal to 4
. So for example the difference between the addresses of the first and the second element is equal to
973077716
-
973077712
=========
000000004
The address of an array is the address of the extent of memory occupied by the array. And obviously it is the address of the first element of the array. So values of the expressions
&array[0]
and
&array
are the same. But expressions themselves have different types. The first expression has the type int *
while the second expression has the type int ( * )[3]
.
Pay attention that using the conversion specifier d with pointers in calls of printf is incorrect. For example instead of these records
printf("value of arrays : %d\n", arrays);
printf("value of &arrays : %d\n", &arrays);
you have to write
printf("value of arrays : %p\n", ( void * )arrays);
printf("value of &arrays : %p\n", ( void * )&arrays);
Arrays used in expressions with rare exceptions are converted to pointers to their first elements.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
CodePudding user response:
two things that cause me problems :
- The first is that in the RAM each of the boxes that make up the table follows one another
This is true, supposing that by "table" you mean "array".
- The second is that a table is a pointer that points to the first box of the table
This is false, and manifestly incompatible with the previous statement.
However, in most places where an array's name or some other array-valued expression is evaluated, the (array) result is automatically converted to a pointer to the first element of the array.
when I do this I notice that the addresses do not follow each other :
int arrays[3] = {10, 20, 30}; int i = 0; for (i=0 ; i < 3 ; i ) { printf("%d : %d\n", i, &arrays[i]); }
Result : 0 : 973077712 1 : 973077716 2 : 973077720
Formally, that tells you nothing, because its behavior is undefined. The correct printf
formatting directive for pointers is %p
, not %d
, and technically, it is appropriate only for pointers to void
. The mismatch between the format directive and the data type of the corresponding argument produces UB. Instead, you want this:
printf("%d : %p\n", i, (void *) &arrays[i]);
However, you will likely find that the (hexadecimal) results still are not sequential numbers. That would be because objects of type int
require more than one unit of storage each. The difference between the addresses of consecutive int
units in your array is the size in bytes of one int
.
And when I do this I notice that array and &array give me the same value which should not be the case for a "classic pointer" :
printf("value of arrays : %d\n", arrays); printf("value of &arrays : %d\n", &arrays);
Result : value of arrays : 1522530048 value of &arrays : 1522530048
Again, undefined behavior. But you would see similar from the correct code. This is because of the automatic conversion of arrays to pointers that I described above, and from the fact that one of the few exceptions to that behavior is when an array-valued expression is the operand of the address-of (unary &
) operator. Thus arrays
is automatically converted to a pointer to the first array element, and &arrays
evaluates to a pointer to the whole array. These have different (pointer) types, but the address of the first element is the same as the address of the whole array.