Reputation: 361
I have a very strange example of pointers, which requires your kind help. In general, pointers are used to point to a variable (see first example below), but when it points to an array. I don't understand why it no longer requires deferencing to obtain the array (see second example below)
printf("TEST: %i\n", x[i]);// I expect this should be *x[i]
This is indeed very strange. Is it just a C convention or how do you explain this?
EDIT::Since many have provided a clear answer, I want to include another small follow up question, as all of you mentioned x[i] = *(x+i), what about x[i][j] for a 2 dimensional array? what is it equivalent to ? Does it require dereferencing?
With a normal variable
int j = 4;
int* pointerj=&j;//pointerj holds address of j or points to j
printf("%d",*pointerj); returns the value that pointer j points to
With an array :
#include <stdio.h>
#include <stdlib.h>
int *function(unsigned int tags) {
int i;
int *var;
var = (int*)malloc(sizeof(int)*tags); // malloc is casted to int* type , allocated dynamical memory, it returns a pointer!
//so now var holds the address to a dynamical array.
for (i = 0; i < tags; i++) {
var[i] = i;
}
return var;
}
int main() {
int *x;
int i;
x = function(10);
for (i = 0; i < 10; i++) {
printf("TEST: %i\n", x[i]);// I expect this should be *x[i]
}
free(x); x = NULL;
return 0;
}
Upvotes: 0
Views: 110
Reputation: 134336
don't understand why it no longer requires dereferencing to obtain the array (element)
Well, you are dereferencing, it's just not using the dereference operator *
.
The array subscripting operator []
is serving as job of dereferencing here. quoting C11
, chapter §6.5.2.1
A postfix expression followed by an expression in square brackets
[]
is a subscripted designation of an element of an array object. The definition of the subscript operator[]
is thatE1[E2]
is identical to(*((E1)+(E2)))
. Because of the conversion rules that apply to the binary+
operator, ifE1
is an array object (equivalently, a pointer to the initial element of an array object) andE2
is an integer,E1[E2]
designates theE2
-th element ofE1
(counting from zero).
It's a syntactic sugar. The expressions x[i]
and *(x+i)
are equivalent. The later satisfies your expectation, whereas, the first one, disguises the dereference operator, but does the exact same job you expected.
That said, also follow the data type closely. What you were expecting, something along the line of *x[i]
would be plain invalid, as it boils down to something like `((x+i) ). Now,
x
is of type int []
(integer array, which decays to a pointer to integer)x+i
gives you a pointer to int
type result.int
.*
, now will try to operate on an operand of type int
(not a pointer), and, this operation will be a syntactical error, as, the constraint for dereference operator says,The operand of the unary
*
operator shall have pointer type.
in C11
, chapter §6.5.3.2.
Answering the additional question:
Let me use the quote, once again, this one's from paragraph 2, chapter §6.5.2.1
Successive subscript operators designate an element of a multidimensional array object. If
E
is ann
-dimensional array(n ≥ 2)
with dimensionsi × j × . . . × k
, thenE
(used as other than an lvalue) is converted to a pointer to an(n − 1)
-dimensional array with dimensionsj × . . . × k
. If the unary*
operator is applied to this pointer explicitly, or implicitly as a result of subscripting, the result is the referenced(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).Consider the array object defined by the declaration
int x[3][5];
Here
x
is a3 × 5
array ofint
s; more precisely,x
is an array of three element objects, each of which is an array of five ints. In the expressionx[i]
, which is equivalent to(*((x)+(i)))
,x
is first converted to a pointer to the initial array of five ints. Theni
is adjusted according to the type ofx
, which conceptually entails multiplyingi
by the size of the object to which the pointer points, namely an array of fiveint
objects. The results are added and indirection is applied to yield an array of five ints. When used in the expressionx[i][j]
, that array is in turn converted to a pointer to the first of the ints, sox[i][j]
yields anint
.
Upvotes: 4
Reputation: 996
the simple answer to your question is that :
The name of array is pointer to first element of array.
Upvotes: 1
Reputation: 12817
You misunderstood how arrays work. Indeed, when using a variable such as int
you should access it's address by
int x;
int *p2x = &x
but when using array, it's a bit different. int y[SOME_SIZE];
is a chunk of bytes in the memory, and *y
will take you to the first element in that memory location, and dereference it. y[0]
will do the same. *y[0]
will first take the value in y[0]
and then will try to dereference it... not what you usually want :(
Upvotes: 1
Reputation: 159
In C, doing x[i] is equivalent (yeah I know) at i[x]. Your compiler compiles this by doing :
*(x+i), where you retrieve your favorite symbole.
x+i is a pointer where you start from x and advance by i. The result takes account of the type of the pointer (0xff is not the same address for a char* than for a int*).
Upvotes: 1
Reputation: 7441
This is ok. No * there.
If you have pointer int *a
which points to array of valid data, for example:
int *a;
int arr[5] = {1, 2, 3, 4, 5];
a = arr;
By using a[0]
you are already dereferencing pointer and *
is not required as a[0]
is the same as *(a + 0)
.
You can go further and even more complicate code for readers.
You may use i[x]
in your example instead of x[i]
. Why?
x[i]
is equal to *(x + i)
but it is also equivalent to *(i + x)
which is what arrays are in C.
It works even with numbers, such as x[3]
or 3[x]
will give you the same result.
Upvotes: 1