473,657 Members | 2,395 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 12983
On Sun, 10 Jul 2005 19:51:22 +0400, Alexei A. Frounze wrote:
"Maxim S. Shatskih" <ma***@storagec raft.com> wrote in message
news:da******** ***@gavrilo.mtu .ru...
Surely.

"&alnt3" is the same as "alnt3", since alnt3 is an array.


It's not. :) The values are identical, but the types aren't, strictly
speaking.


Everything else you've said is spot on, but this is slightly incorrect.
You are right that the values are identical when the array is not a
function parameter. i.e.

#include <stdio.h>
int glob_array[5];

int main(void)
{
int fn_array[5];

if ((&glob_array != glob_array) || (&fn_array != fn_array))
printf("I haven't seen a situation like this before.\n");
}

I don't know however, whether this is mandated by the standard - in
theory it isn't necessary for it to be true, but in practice it would
waste space for it not to be.

However in the context of a function parameter, it is not true. Given
that in C parameters are passed by value, it's not possible for the
address of the array parameter to equal the address of the original array
and therefore it's not possible for the address of the array parameter to
equal the address of the first element that it points to. i.e. we can
write:

#include <stdio.h>
void somefunction(in t arrayparm[5])
{
if (arrayparm == &arrayparm)
printf("Somethi ng impossible has occurred.\n");
}

Nov 15 '05 #31
Alexei A. Frounze wrote:
"Tommi Johnsson" <TE*@Merlin.Mir rorland> wrote in message
news:4L******** ********@reader 1.news.jippii.n et...
Alexei A. Frounze wrote:
Yes, this would work fine if aInt3[] were declared as const array... But
the
problem is that the compiler allows pointers to consts to non-const data
but
warns on pointers to const array to non-const data. That's why I
presented
both things in the test program. Kinda odd, don't you think so? I mean,
I
can put there a type cast to get rid of the warning, but this warning in
its
very core is stupid. Why "const int*" should be better than or in any
other
way differ from "const (*int)[]"? Where's the rationale? I don't see it.
Any
idea?
i think, it's because types differs from each other...
in print1 you declare `p` as an pointer to const qualified int.
-->> pointed value is const qualified
and
in print2 you declare `p` as an pointer to const qualified array of ints
-->> pointed value is array which elements are const qualified.

i see `const int **p` more like `const int (*p)[5]` than `const int *p`
in this case, because array decays to pointer in most cases.

- jt

There were no "const int **p" in the code. Besides, "const int **p" declares
a modifiable pointer to a modifiable pointer to a constant int. There's no
double indirection anywhere in the code.

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

Can it be declared like that provided the compiler does not emit any warning
if as argument I use an array (its address) that isn't constant?


Try this one...
Array decays to pointer while array is passed to the function...

int aInt[5] = {1,2,3,4,5};

void print (const int p[5]) {
int x = 25;
if (__builtin_type s_compatible_p (typeof (p), const int * ))
printf ("trallalalaa.. .");
printf ("%d %d %d\n", sizeof (p), sizeof (int[5]), sizeof (const
int *));
//*p[0] = 3;
printf ("%d\n", p[0]);
p = &x;
printf ("%d\n", *p);
}

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

print (aInt);

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

Why can I do it with one value, e.g. pass a pointer to modifiable int or
modifiable array of ints to a function whose argument is of type "const
int*", but I can not do the same with an array of fixed number of ints?

Alex

Nov 15 '05 #32
> 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?
The C notion of the array is another. Array is the same as pointer to its first
element (in all operations except sizeof(), and so ( p + a ) offset
operations).
What is "the pointer" to which you are referring?
MyArray and &(MyArray[0]) is the same in all contexts except sizeof().
absurd - a pointer to an array is much more than just an address.
In C and C++, it is the same.
doubt that you mean that. Generally a pointer is a variable...


Pointer is a value. Value != variable.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
ma***@storagecr aft.com
http://www.storagecraft.com
Nov 15 '05 #33
On Sun, 10 Jul 2005 23:35:38 +0300, Tommi Johnsson wrote:
Alexei A. Frounze wrote:
Yes, this would work fine if aInt3[] were declared as const array... But the
problem is that the compiler allows pointers to consts to non-const data but
warns on pointers to const array to non-const data. That's why I presented
both things in the test program. Kinda odd, don't you think so? I mean, I
can put there a type cast to get rid of the warning, but this warning in its
very core is stupid. Why "const int*" should be better than or in any other
way differ from "const (*int)[]"? Where's the rationale? I don't see it. Any
idea?

An array of ints is a fundamentally different type of object to a an int.
So a pointer to an array of ints is quite different to a pointer to an
int, because the properties of a pointer depend very much on the type of
thing they point at.
i think, it's because types differs from each other...
in print1 you declare `p` as an pointer to const qualified int.
-->> pointed value is const qualified
and
in print2 you declare `p` as an pointer to const qualified array of ints
-->> pointed value is array which elements are const qualified.

i see `const int **p` more like `const int (*p)[5]` than `const int *p`
in this case, because array decays to pointer in most cases.


But this is an important example of where that is not the case. In
const int (*p)[5] p is already a pointer, it cannot "decay" further. This
array -> pointer conversion is only applicable at the top level of a type.
It is important to remmeber that arrays and pointers really are
fundamentally different types, although their operation is naturally
connected.

Lawrence
Nov 15 '05 #34
[Given "int arr[N];" and considering "&arr" vs "&arr[0]")
On Sun, 10 Jul 2005 19:51:22 +0400, Alexei A. Frounze wrote:
It's not. :) The values are identical, but the types aren't, strictly
speaking.

In article <pa************ *************** *@dodo.com.au>,
Netocrat <ne******@dodo. com.au> wrote:Everything else you've said is spot on, but this is slightly incorrect.
Actually, it is completely correct. :-) But it does not tell you
all that much by itself: as I have shown before, the values of
3 and 3.14 are identical too:

int i = 3;
double d = 3.14;

if ((char)i == (char)d)
puts("3 and 3.14 are identical");
else
puts("3 and 3.14 are different");

Obviously they are only "identical" after conversion to a common
type -- in this case "char" -- and the results may (and do) change
if we pick a different common type:

if ((float)i == (float)d)
puts("3 and 3.14 are identical");
else
puts("3 and 3.14 are different");

To compare &arr against &arr[0], we have to convert to a common
type; and as with the int/double arrangement above, this may change
the value(s) in the process:
#include <stdio.h>
int glob_array[5];

int main(void)
{
int fn_array[5];

if ((&glob_array != glob_array) || (&fn_array != fn_array))
printf("I haven't seen a situation like this before.\n");
}
If you actually compile this, you get the required diagnostic,
and in this particular case, two more diagnostics:

% cc -O2 -W -Wall -ansi -pedantic -o t t.c
t.c: In function `main':
t.c:8: warning: comparison of distinct pointer types lacks a cast
t.c:8: warning: comparison of distinct pointer types lacks a cast
t.c:10: warning: control reaches end of non-void function

(the C standard requires only that "at least one diagnostic" come
out, and does not say whether it is a "warning", or an "error", or
even a "kumquat"). We can fix this by inserting a conversion to
some common type: for instance, we could cast both to "char *".
But introducing a conversion gets us back to that 3==3.14 problem.
I think the real question boils down to whether &arr and &arr[0]
will compare equal under *all* "well-defined" conversions -- which
may even be only those to "char *" and "void *" -- and then I think
the answer is "yes", so that we can in fact say that the converted
values are always identical as long as we do a sensible conversion.

But, onward:
However in the context of a function parameter, it is not true. Given
that in C parameters are passed by value, it's not possible for the
address of the array parameter to equal the address of the original array
and therefore it's not possible for the address of the array parameter to
equal the address of the first element that it points to. i.e. we can
write:

#include <stdio.h>
void somefunction(in t arrayparm[5])
{
if (arrayparm == &arrayparm)
printf("Somethi ng impossible has occurred.\n");
}


The real problem here is "what you see, well, all of it's a lie"[%].
The variable named "arrayparm" has type "pointer to int", not "array
5 of int". We can expose the lie via various operators:

/* these sizes will differ (unless you get VERY unlucky) */
printf("sizeof (int [5]) = %lu\n", (unsigned long)sizeof (int [5]));
printf("sizeof arrayparm = %lu\n", (unsigned long)sizeof arrayparm);

/* cannot do this with an array */
arrayparm = NULL;

and of course, your own example, once we insert some appropriate
conversions to eliminate the need for a diagnostic (and perhaps no
executable program as a consequence of the diagnostic):

printf("%p != %p, we presume\n", (void *)arrayparm, (void *)&arrayparm);
if ((void *)arrayparm != (void *)&arrayparm)
puts("we presumed correctly");
else
puts("uh oh");

[% "Wine from the Water", from Try Anything Once]
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 15 '05 #35
On 11 Jul 2005 17:35:54 GMT, Chris Torek
<no****@torek.n et> wrote:
[Given "int arr[N];" and considering "&arr" vs "&arr[0]")

I think the real question boils down to whether &arr and &arr[0]
will compare equal under *all* "well-defined" conversions -- which
may even be only those to "char *" and "void *" -- and then I think
the answer is "yes", so that we can in fact say that the converted
values are always identical as long as we do a sensible conversion.


Is that actually defined by the standard? I remember that in some
pre-standard C compilers arrays were actually implemented as pointers,
so int arr[5]; would actually expand to the equivalent in
pseudo-assember:

arr: dw &_arr
_arr: dw ?[5]

(The array pointer itself might be declared in a read-only segment.)

Is this sort of expansion actually banned by the standard, or is it
"just not the done thing"?

In those compilers the effect would be the same as happens with "array
parameters", taking &arr would get you the address of the pointer.

Chris C
Nov 15 '05 #36
Alexei A. Frounze wrote:
...
So, I presume nobody knows what's wrong. I haven't found anything on this
particular thing in C99. Maybe it's just gcc's way to do things... I need
more statistics.
...


What's wrong in the original case is perfectly clear here. The warning is a
consequence of C language's const-correctness rules when they are applied to
arrays (and it's been mentioned here already).

Simply speaking, in accordance with C language's const correctness rules, you
can perform an implicit 'T* -> const T*' conversion. Often people assume that,
say, 'int (*)[10] -> const int (*)[10]' conversion also belongs to that category
and should be performed implicitly without any warnings (that's what you
assumed, apparently). Unfortunately, this is not the case. In C language it is
not possible to const-qualify an array type as a whole. Period. Any attempts to
const-qualify an array type will actually const-qualify the type of the array
_elements_ not the array type itself. In other words, there's no situation in C
when the 'T* -> const T*' can be applied to pointers-to-arrays, since the proper
destination type cannot ever exist in C.

Best regards,
Andrey Tarasevich
Nov 15 '05 #37
Lawrence Kirby wrote:
On Sun, 10 Jul 2005 23:35:38 +0300, Tommi Johnsson wrote:

Alexei A. Frounze wrote:
Yes, this would work fine if aInt3[] were declared as const array... But the
problem is that the compiler allows pointers to consts to non-const data but
warns on pointers to const array to non-const data. That's why I presented
both things in the test program. Kinda odd, don't you think so? I mean, I
can put there a type cast to get rid of the warning, but this warning in its
very core is stupid. Why "const int*" should be better than or in any other
way differ from "const (*int)[]"? Where's the rationale? I don't see it. Any
idea?


An array of ints is a fundamentally different type of object to a an int.
So a pointer to an array of ints is quite different to a pointer to an
int, because the properties of a pointer depend very much on the type of
thing they point at.

i think, it's because types differs from each other...
in print1 you declare `p` as an pointer to const qualified int.
-->> pointed value is const qualified
and
in print2 you declare `p` as an pointer to const qualified array of ints
-->> pointed value is array which elements are const qualified.

i see `const int **p` more like `const int (*p)[5]` than `const int *p`
in this case, because array decays to pointer in most cases.

But this is an important example of where that is not the case. In
const int (*p)[5] p is already a pointer, it cannot "decay" further.


in declaration like const int (*p)[5] it declares only type for p it
really doesnt decay anything but above in 1.st and 2.nd declaration of
pointer p, p is needed to indirect before using p pointed value as an
array, in 3.rd declaration there is no need for that and in later use
p pointed array will decay to the pointer when indirected throught it, i
suppose.

- jt

This
array -> pointer conversion is only applicable at the top level of a type.
It is important to remmeber that arrays and pointers really are
fundamentally different types, although their operation is naturally
connected.

Lawrence

Nov 15 '05 #38
Netocrat wrote:
On Sun, 10 Jul 2005 18:01:17 -0700, Old Wolf wrote:
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])


Ah, you are correct.

Nov 15 '05 #39
"Netocrat" <ne******@dodo. com.au> wrote in message
news:pa******** *************** *****@dodo.com. au...
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 */


Correct, but I don't think it's a good example. Simply being able to modify
something by pc and being unable to modify it by ppc is just fine, so is in
the simpler example:
char c = 'A';
char *pc = &c;
const char *pc_ = &c;
*pc = 'B'; // OK
*pc_ = 'B'; // prohibited
This is how most of libc's functions are declared -- their arguments are of
type of a pointer to a constant value.
This is what I'd like to have with the array too.
I'm not really sure why enforcing protection in this simple case above is OK
(i.e. pc=&c;) but not OK in case of using the array as an object to be
passed by reference/pointer.
I'm fine with warnings and errors caused by the improper use of a pointer to
a constant object, e.g. attempt to modify the constant object. That's
perfectly understandable. Why cannot I enforce such a protection by treating
some object (not necessarily one defined as constant) as a constant one --
that's something I don't get, no matter if there's double indirection or
not. I'm puzzled. What else am I missing?

Alex
Nov 15 '05 #40

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

Similar topics

8
4432
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
3623
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
2138
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
8306
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8825
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. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8732
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 captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8503
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 most users, this new feature is actually very convenient. If you want to control the update process,...
0
5632
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 into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4152
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4304
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2726
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
2
1955
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.