473,569 Members | 2,683 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

gcc: pointer to array

Hi all,

I have a question regarding the gcc behavior (gcc version 3.3.4).

On the following test program it emits a warning:
#include <stdio.h>

int aInt2[6] = {0,1,2,4,9,16};
int aInt3[5] = {0,1,2,4,9};

void print1 (const int* p, size_t cnt)
{
while (cnt--)
printf ("%d\n", *p++);
}

void print2 (const int (*p)[5])
{
size_t cnt;
#if 0
// prohibited:
(*p)[0]=0;
#endif
for (cnt=0; cnt<5; cnt++)
printf ("%d\n", (*p)[cnt]);
}

int main()
{
printf ("test begin\n");

print1 (aInt2, sizeof(aInt2)/sizeof(aInt2[0]));
print2 (&aInt3); // <-- warns here

printf ("test end\n");
return 0;
}

The warning is:
MOD.c: In function `main':
MOD.c:: warning: passing arg 1 of `print2' from incompatible pointer type

Why is that? How is this different from using print1 (aInt2, ...)? All I
want to do is to explicitly show that the pointer is to an array of 5
entries and ensure that it's not modified in anyway inside print2(). However
the #if 0'd assignment operator inside print2() is correctly handled by
gcc -- an error is generated:
MOD.c: In function `print2':
MOD.c:: error: assignment of read-only location
What's wrong with gcc?

There's another thing about the pointer to the array is... The compiler
doesn't generate a warning if I change in print2()
for (cnt=0; cnt<5; cnt++)
to
for (cnt=0; cnt<6; cnt++)
and lets me access (*p)[5], though I think at least a warning should be
generated here.
It doesn't warn me if I put
aInt3[6] = 0;
into main(). But in both cases the compiler "knows" the real size of the
array, still no warning...
Is this OK???

Thanks,
Alex
P.S. I compile it as gcc MOD.c -Wall -oMOD.exe
Nov 15 '05
204 12938
On Mon, 11 Jul 2005 01:39:21 +0400, Alexei A. Frounze wrote:
"Al Bowers" <ab*****@myrapi dsys.com> wrote in message
news:3j******** ****@individual .net...


Alexei A. Frounze wrote:
> "Al Bowers" <ab*****@myrapi dsys.com> wrote in message
> news:3j******** ****@individual .net... ...
>
>>Try removing the const keyword.
>
> ...
>
> But I want to keep it. :)
>
> If castration of const is out, do not pout. Casting, a pollution, is one
solution.

Very smart :)
(const int (*)[5])


This is even smarter. :)

So, I presume nobody knows what's wrong.


Well it's strange that you haven't had a more direct explanation as to
why the problem is occurring as yet.
I haven't found anything on this
particular thing in C99.
I'm not sure if it's in C90 or C99... I haven't looked myself but see the
thread I refer to in my other post which mentions it as being in standard
C++.
Maybe it's just gcc's way to do things... I need more statistics.


I haven't consulted the standards and don't know whether gcc is complying
with C90 or C99. But intuitively it is correct behaviour - double
indirection can easily be used to gain access to the supposedly protected
const type by assigning the middle pointer to a non-const pointer.
There's no way the compiler can detect this, so disallowing automatic
const-conversion for double-indirection parameters makes sense.

Nov 15 '05 #21
On Mon, 11 Jul 2005 09:22:08 +1000, Netocrat wrote:
Anyway, can you suggest a declaration of the function's argument that
would simultaneously satisfy:
- being a pointer to an array of a fixed number of elements, say, 5
integers - this array is to be constant, in other words, its elements
can't be altered by using the pointer


No. To the best of my understanding it is not possible according to the
standard.


Disclaimer: my knowledge of the standard is very patchy and I made this
statement based on the thread that I referenced - but looking at it again
I see that there is no actual mention of C90 or C99 - just C++ standards.
So I really don't know what the standard says about this and I'm not
motivated to go hunting through the drafts to find out. You say you've
looked and can't find anything: perhaps one of the standards gurus of this
group can clarify. It is intuitively correct behaviour though whether
standards-specified or not.

Nov 15 '05 #22
Alexei A. Frounze wrote:
I have a question regarding the gcc behavior (gcc version 3.3.4).

On the following test program it emits a warning:
#include <stdio.h>

int aInt3[5] = {0,1,2,4,9};

void print2 (const int (*p)[5])
{
}

int main()
{
print2 (&aInt3); // <-- warns here
return 0;
} The warning is:
MOD.c: In function `main':
MOD.c:: warning: passing arg 1 of `print2' from incompatible pointer type
The compiler is correct. The pointers point to incompatible types;
the element type of one array is const-qualified, and it isn't in the
other. Type compatibility is recursive, and types with different
qualifiers are not compatible.

Either the function needs to lose the const qualifier, or you need to
add it to your array.
There's another thing about the pointer to the array is... The compiler
doesn't generate a warning if I change in print2()
for (cnt=0; cnt<5; cnt++)
to
for (cnt=0; cnt<6; cnt++)
and lets me access (*p)[5], though I think at least a warning should be
generated here.
That's hard as it has to follow what your program is doing, not just
the syntax. It's certainly possible to warn, though; some lint
programs would.
It doesn't warn me if I put
aInt3[6] = 0;
into main(). But in both cases the compiler "knows" the real size of the
array, still no warning...


That's easy to warn about and GCC should do it. I suggest you file an
enhancement request.

Nov 15 '05 #23
Alexei A. Frounze wrote:

I have a question regarding the gcc behavior (gcc version 3.3.4).
You got an unusually high number of garbage responses :)
On the following test program it emits a warning:
#include <stdio.h>

int aInt3[5] = {0,1,2,4,9};

void print2 (const int (*p)[5])
{
size_t cnt;
for (cnt=0; cnt<5; cnt++)
printf ("%d\n", (*p)[cnt]);
}

int main()
{
print2 (&aInt3); // <-- warns here
return 0;
}

MOD.c:: warning: passing arg 1 of `print2' from incompatible pointer type


print2 is expecting a pointer to an array of constant ints.

Note, you can't have a "const array" in C -- you can
only have an array whose members are all const.

aInt3 is an array of ints, and there is no implicit conversion
in C from pointer-to-array-of-T to pointer-to-array-of-const-T
(or an array of anything else, for that matter). This could be
considered a language defect.

But, this does work:
typedef int (*P5INT)[5];
void print2(const P5INT p)
{

AFAIK it's not possible to do this without a typedef.

Nov 15 '05 #24
On Sun, 10 Jul 2005 18:01:17 -0700, Old Wolf wrote:
[T]here is no implicit conversion in C from pointer-to-array-of-T to
pointer-to-array-of-const-T (or an array of anything else, for that
matter). This could be considered a language defect.
In this case it certainly would be useful. I don't see how any harm could
be done.
But, this does work:
typedef int (*P5INT)[5];
void print2(const P5INT p)
{
Not as the OP intended though. It is an equivalent prototype to:
void print2(int (*const p)[5])

So it does allow the function to be called as the OP desired - ie with a
non-const array - and without a cast - but it also removes the desired
const protection... you can now assign to (*p)[0] within the function.
The semantics of your parameter are to make p itself const, rather than
what it points to. i.e. if you add to the function:

int pp[5];
p = &pp;

you will get a warning about attempting to write to a read-only location.
AFAIK it's not possible to do this without a typedef.


It is though, as per above.

Nov 15 '05 #25
On Mon, 11 Jul 2005 09:29:27 +1000, Netocrat wrote:
[D]ouble indirection can easily be used to gain access to the supposedly
protected const type by assigning the middle pointer to a non-const
pointer. There's no way the compiler can detect this, so disallowing
automatic const-conversion for double-indirection parameters makes sense.


I'm talking nonsense. You can't assign the middle pointer to a non-const
pointer without a cast. But you can use the automatic conversion to
violate the const protection: quoting "Me" in another thread:

const char c = 'c';
char * pc;
const char ** pcc = & pc ; /* not allowed */
*pcc = & c;
*pc = 'C'; /* would modify a const object if the conversion above were
* allowed */

Nov 15 '05 #26
On Mon, 11 Jul 2005 12:38:37 +1000, Netocrat wrote:
On Sun, 10 Jul 2005 18:01:17 -0700, Old Wolf wrote:
[T]here is no implicit conversion in C from pointer-to-array-of-T to
pointer-to-array-of-const-T (or an array of anything else, for that
matter). This could be considered a language defect.


In this case it certainly would be useful. I don't see how any harm could
be done.


OK I take that back after reading another thread - harm could be done.
It's definitely not a defect but a required safety mechanism.

Nov 15 '05 #27
> A pointer to an array *is* double indirection.

No. It is absolutely the same as the pointer to its first element.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
ma***@storagecr aft.com
http://www.storagecraft.com
Nov 15 '05 #28
On Mon, 11 Jul 2005 14:01:57 +0400, Maxim S. Shatskih wrote:
A pointer to an array *is* double indirection.
No.


An array is one layer of indirection. Given its similarity to a pointer I
don't see much controversy in that statement. A pointer to an array is
therefore a second layer of indirection. What do you find disagreeable
about this reasoning?
It is absolutely the same as the pointer to its first element.


What is "the pointer" to which you are referring? Do you mean the
address of its first element? In that case your statement is plainly
absurd - a pointer to an array is much more than just an address. So I
doubt that you mean that. Generally a pointer is a variable... but
we've only got one variable here, and you can't be claiming equivalence
with itself since that is true but meaningless. So what _do_ you mean?

Your statement is also vague because "first element" could be applied to
the array pointer or to the array that it points to. You don't make it
clear which you mean. i.e. given:

int (*ap)[5] = &a;

it is possible to access "it's first element" as ap[0] or (*ap)[0].

Although your statement is vague, I interpret it to be saying that

ap == &(*ap)[0]

which I don't disagree with. Since you are disagreeing with my double
indirection statement though, you perhaps would also be arguing that

ap[0] == (*ap)[0]

That's true, but a pointer to an object can be treated as an array of
those objects and this is no less true for pointers to arrays - which can
be treated as arrays of arrays. So for index other than 0

ap[index] != (*ap)[index]

In fact accessing ap[1] in this instance is illegal but conceptually it is
an access of the second "5 element integer array" element of ap. We can
make it valid by doing this:
ap = malloc(sizeof(a ) * 10);
if (!ap) abort_no_mem();

Now we can write things like ap[7][4] which accesses the 5th (and last)
element of the 8th "5 element integer array" in the array of "5 element
integer arrays" which, given our ability to index a pointer as an array,
we can consider ap as representing.

Again demonstrating that a pointer to an array has two layers of
indirection. In any case I found your statement unclear so I have made
a few assumptions but I may have missed your point.

Nov 15 '05 #29
On Mon, 11 Jul 2005 21:06:45 +1000, Netocrat wrote:
On Mon, 11 Jul 2005 14:01:57 +0400, Maxim S. Shatskih wrote:
A pointer to an array *is* double indirection.
No.


An array is one layer of indirection. Given its similarity to a pointer I
don't see much controversy in that statement. A pointer to an array is
therefore a second layer of indirection. What do you find disagreeable
about this reasoning?
It is absolutely the same as the pointer to its first element.


What is "the pointer" to which you are referring? Do you mean the address
of its first element? In that case your statement is plainly absurd - a
pointer to an array is much more than just an address. So I doubt that
you mean that. Generally a pointer is a variable... but we've only got
one variable here, and you can't be claiming equivalence with itself since
that is true but meaningless. So what _do_ you mean?

Your statement is also vague because "first element" could be applied to
the array pointer or to the array that it points to. You don't make it
clear which you mean. i.e. given:


I left this out:

int a[5];
int (*ap)[5] = &a;

it is possible to access "it's first element" as ap[0] or (*ap)[0].

Although your statement is vague, I interpret it to be saying that

ap == &(*ap)[0]

which I don't disagree with. Since you are disagreeing with my double
indirection statement though, you perhaps would also be arguing that

ap[0] == (*ap)[0]

That's true, but a pointer to an object can be treated as an array of
those objects and this is no less true for pointers to arrays - which can
be treated as arrays of arrays. So for index other than 0

ap[index] != (*ap)[index]

In fact accessing ap[1] in this instance is illegal but conceptually it is
an access of the second "5 element integer array" element of ap. We can
make it valid by doing this:
ap = malloc(sizeof(a ) * 10);
if (!ap) abort_no_mem();

Now we can write things like ap[7][4] which accesses the 5th (and last)
element of the 8th "5 element integer array" in the array of "5 element
integer arrays" which, given our ability to index a pointer as an array,
we can consider ap as representing.

Again demonstrating that a pointer to an array has two layers of
indirection. In any case I found your statement unclear so I have made a
few assumptions but I may have missed your point.


Nov 15 '05 #30

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
4429
by: pemo | last post by:
I've just been trying out the Watcom compiler from http://www.openwatcom.org, and almost immediately compiled some working source that errored. The code is char buffer; ...
34
3610
by: thibault.langlois | last post by:
Hello, I get a warning when I compile: #include <string.h> int main (int argc, char ** argv) { char * s; s = strdup("a string"); return 0; }
7
2133
by: vippstar | last post by:
Today I got a confusing message from gcc (I'm aware, those don't break conformance ;-) In function 'main': 7: warning: format '%d' expects type 'int', but argument 2 has type 'char (*)' The code is #include <stdio.h>
0
7698
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7924
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8122
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7673
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
6284
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5219
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3640
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2113
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1213
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.