Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion about dereference operator ("*") in C

As far as I know, the derefence operator * returns the value stored in the pointer address. What I'm confused by is the behavior when the operator is used with pointer of an array. For example,

int a[4][2];

Then a is internally converted to pointer of first element of array of 4 elements of 2 ints. Then which value does *a return? I'm really confused!

like image 926
Jin Avatar asked Aug 06 '16 00:08

Jin


People also ask

What does the dereference operator (*) do?

In computer programming, a dereference operator, also known as an indirection operator, operates on a pointer variable. It returns the location value, or l-value in memory pointed to by the variable's value. In the C programming language, the deference operator is denoted with an asterisk (*).

Why would you use the operator * to dereference a pointer?

Dereferencing is used to access or manipulate data contained in memory location pointed to by a pointer. *(asterisk) is used with pointer variable when dereferencing the pointer variable, it refers to variable being pointed, so this is called dereferencing of pointers.

What is dereferencing operator in C?

The dereference operator is also known as an indirection operator, which is represented by (*). When indirection operator (*) is used with the pointer variable, then it is known as dereferencing a pointer. When we dereference a pointer, then the value of the variable pointed by this pointer will be returned.

Which C operator is used to dereference a pointer?

The unary operator * is used to declare a pointer and the unary operator & is used to dereference the pointer.. In both cases, the operator is “unary” because it acts upon a single operand to produce a new value.


2 Answers

The type of a is int[4][2], so the type of *a (or equivalently a[0]) is int[2].

It is not the same as a[0][0]. If you do this:

int a[4][2];
printf("%d\n",*a);

The compiler will tell you this:

warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘int *’

Since an array (in this case one of type int [2]) is being passed to a function, it decays to a pointer to the first element in this context.

If on the other hand you had **a, that is equivalent to a[0][0] and has type int.

like image 173
dbush Avatar answered Oct 16 '22 14:10

dbush


This:

int a[4][2];

defined a an array of 4 elements, each of which is an array of 2 int elements. (A 2-dimensional array is nothing more or less than an array of arrays.)

An array expression is, in most contexts, implicitly converted to a pointer to the array object's initial (zeroth) element. (Note the assumption that there is an array object; that has caused some angst, but it's not relevant here.)

The cases where an array expression is not converted to a pointer are:

  • When it's the operand of sizeof;
  • When it's the operand of unary &; and
  • When it's a string literal in an initializer used to initialize an array object.

(Compiler-specific extensions like gcc's typeof might create more exceptions.)

So in the expression *a, the subexpression a (which is of type int[4][2]) is implicitly converted to a pointer of type int(*)[2] (pointer to array of 2 ints). Applying unary * dereferences that pointer, giving us an expression of type int[2].

But we're not quite done yet. *a is also an expression of array type, which means that, depending on how it's used, it will probably be converted again to a pointer, this time of type int*.

If we write sizeof *a, the subexpression a is converted from int[4][2] to int(*)[2], but the subexpression *a is not converted from int[2] to int*, so the expression yields the size of the type int[2].

If we write **a, the conversion does occur. *a is of type int[2], which is converted to int*; dereferencing that yields an expression of type int.

Note that despite the fact that we can legally refer to **a, using two pointer dereference operations, there are no pointer objects. a is an array object, consisting entirely of 8 int objects. The implicit conversions yield pointer values.

The implicit array-to-pointer conversion rules are in N1570 section 6.3.2.1 paragraph 3. (That paragraph incorrectly gives _Alignof as a fourth exception, but _Alignof cannot be applied to an expression. The published C11 standard corrected the error.)

Recommended reading: Section 6 of the comp.lang.c FAQ.

like image 44
Keith Thompson Avatar answered Oct 16 '22 14:10

Keith Thompson