pointer to an array vs pointer to pointer

S

subramanian100in

Consider the following program x.c:

#include <stdlib.h>
#include <stdio.h>

int main()
{
int x[10];
int **pp = &x;

pp = NULL; // just to get rid of compiler warning.

return EXIT_SUCCESS;
}

When I compile this program under gcc 3.4.3 as
gcc -std=c99 -pedantic -Wall -Wextra x.c

it merely generates the warning
x.c: In function `main':
x.c:7: warning: initialization from incompatible pointer type

I thought the line
int **pp = &x;
is in error because of different pointer types involved in the
assignment - '&x' is a pointer to an array and 'pp' is a pointer to
pointer.

So I do not understand why the compiler did not generate error for
this line.

Is this behaviour specific to the particular gcc implementation or the
ISO C99 Standard itself does not treat the above assignment as an
error ?

Please clarify.

Thanks
V.Subramanian
 
J

James Kuyper

Consider the following program x.c:

#include <stdlib.h>
#include <stdio.h>

int main()
{
int x[10];
int **pp = &x;

pp = NULL; // just to get rid of compiler warning.

return EXIT_SUCCESS;
}

When I compile this program under gcc 3.4.3 as
gcc -std=c99 -pedantic -Wall -Wextra x.c

it merely generates the warning
x.c: In function `main':
x.c:7: warning: initialization from incompatible pointer type

I thought the line
int **pp = &x;
is in error because of different pointer types involved in the
assignment - '&x' is a pointer to an array and 'pp' is a pointer to
pointer.

So I do not understand why the compiler did not generate error for
this line.

Is this behaviour specific to the particular gcc implementation or the
ISO C99 Standard itself does not treat the above assignment as an
error ?

For initialization of a scalar object by a single expression, 6.7.8p11
says that "the same type constraints and conversions as for simple
assignment apply". 6.5.16.1p1 contains those constraints, listing the
permitted combinations of types for the left and right operands. Since
&x has the type int (*)[10], and p has the type int**, which are not
compatible types, none of those combinations apply. It is therefore a
constraint violation.

The standard makes no distinctions between "errors" and "warnings". It
only talks about diagnostic messages, a term which could cover either.
The standard requires that an implementation must generate at least one
diagnostic for any program that contains a syntax error or a constraint
violation. gcc met that requirement when it issued that warning.

Having generated the mandatory diagnostic, the implementation is free to
continue translating the program. The behavior of the resulting program,
if executed, is undefined. I would guess that gcc probably translated
your code as if it contained an (int**) cast. There's only one feature a
C program can contain that requires the implementation to reject it: a
#error directive that survives conditional compilation.
 
C

Conor F

I thought the line
I think the compiler generates an error if it cannot continue. Most of
the time if it sees something problematic it just warns and then
continues - it tells you there might be a problem with it and then
leaves it up to you to decide. You're the programmer after all - if
that's what you want it's not up to the compiler to actively stop you.

Which is why treating warnings as errors is probably a good plan in
many cases!

Conor.
 
N

Nobody

So I do not understand why the compiler did not generate error for
this line.

Is this behaviour specific to the particular gcc implementation or the
ISO C99 Standard itself does not treat the above assignment as an
error ?

The ISO C standard doesn't say a great deal about dealing with errors.
Specifically:

5.1.1.3 Diagnostics

[#1] A conforming implementation shall produce at least one
diagnostic message (identified in an implementation-defined
manner) if a preprocessing translation unit or translation
unit contains a violation of any syntax rule or constraint,
even if the behavior is also explicitly specified as
undefined or implementation-defined. Diagnostic messages
need not be produced in other circumstances.7)

It doesn't make any distinction between errors or warnings, nor does it
require a diagnostic for each violation, nor does it prohibit the
implementation from issuing diagnostics for valid code (e.g. compilers
will often warn about possible mistakes, such as using an assignment
expression in the test of an if/while/etc, as it's often the case that the
programmer typed "=" when they meant "==").

Consequently, a compiler which simply printed e.g.:

Note: the program may contain errors

for every file which it processed would conform to the requirements of the
standard. It issues the required diagnostic for code which contains
errors, and it issues a not-required-but-permitted diagnostic for code
which doesn't contain errors.
 
S

Stanley Rice

Consider the following program x.c:
#include <stdlib.h>
#include <stdio.h>
int main()
{
        int x[10];
        int **pp = &x;
        pp = NULL;  // just to get rid of compiler warning.
        return EXIT_SUCCESS;
}
When I compile this program under gcc 3.4.3 as
gcc -std=c99 -pedantic -Wall -Wextra x.c
it merely generates the warning
x.c: In function `main':
x.c:7: warning: initialization from incompatible pointer type
I thought the line
    int **pp = &x;
is in error because of different pointer types involved in the
assignment - '&x' is a pointer to an array and 'pp' is a pointer to
pointer.
So I do not understand why the compiler did not generate error for
this line.
Is this behaviour specific to the particular gcc implementation or the
ISO C99 Standard itself does not treat the above assignment as an
error ?

For initialization of a scalar object by a single expression, 6.7.8p11
says that "the same type constraints and conversions as for simple
assignment apply". 6.5.16.1p1 contains those constraints, listing the
permitted combinations of types for the left and right operands. Since
&x has the type int (*)[10], and p has the type int**, which are not
compatible types, none of those combinations apply. It is therefore a
constraint violation.

I am sorry, I couldn't understand why &x has the type int (*)[10],
other a pointer that points to a pointer that points to the initial
element of x.

section
6.3.2.1, paragraph 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.
---

So I think when we reference the array x, it decays to a pointer that
points to initial element of x, that is &x[0], and the line
int **pp = &x;
is somewhat a pointer that points to a pointer that points to the
initial element of x. I think it is OK and why the compiler complains.
 
J

James Kuyper

On 09/23/2011 05:20 AM, Stanley Rice wrote:
....
I am sorry, I couldn't understand why &x has the type int (*)[10],
other a pointer that points to a pointer that points to the initial
element of x.

section
6.3.2.1, paragraph 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.

Look again at the very beginning of that section: "Except when it is the
operand of ... the unary & operator ...". In the expression &x, the
array 'x' is the operand of the unary & operator. Therefore, this
expression is covered by that exception, and no such decay occurs.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top