If b is a 2-D VLA, must it be true that b==&b[0][0]?

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by shenki » Thu, 20 Apr 2006 01:15:43


=====================
#include <stdio.h>
static const int n=3;
int main( int narg, char *arg[] ) {
int a[2][3];
int b[2][n];
int c[3];
int d[n];
printf( "a, &a[0][0]= %p, %p\n", a, &a[0][0] );
printf( "b, &b[0][0]= %p, %p\n", b, &b[0][0] );
printf( "c, &c[0]= %p, %p\n", c, &c[0] );
printf( "d, &d[0]= %p, %p\n", d, &d[0] );
return 0;
}
=======================

One of my compilers gives the following output for the above program:

------------------
a, &a[0][0]= 2ff225d0, 2ff225d0
b, &b[0][0]= 2ff225b8, 2ff225e8
c, &c[0]= 2ff225f8, 2ff225f8
d, &d[0]= 2ff22598, 2ff22598
------------------------

Note the line for b. It is my understanding of the C99 standard that
the two values printed must be identical. They are, in fact, identical
for two other compilers I've tried (on two different hardware
platforms).

Is my program standard-conforming, and are the results shown indeed not
standard-conforming?

Thanks,
-P.
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by Eric Sosma » Thu, 20 Apr 2006 01:43:11


XXXX@XXXXX.COM wrote On 04/18/06 12:15,:

Your program is nonconforming because the argument
corresponding to a "%p" specifier must be of type `void*',
while the arguments you've supplied are not. One quite
often gets away with this, but since your wider question
is specifically about the converted values of the pointers
it would be wise to make the program squeaky-clean before
going further. (Especially since VLA's may cause the
compiler to indulge in all sorts of sneaky maneuvers.)
Please insert `(void*)' casts as needed, try your program
again, and let us know what you got.

--
XXXX@XXXXX.COM

 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by shenki » Thu, 20 Apr 2006 02:51:57

Thanks for the suggestion to cast the pointers to (void*) before
printing. I get the same results. Here are the program and the
output.

============================
int main( int narg, char *arg[] ) {
int a[2][3];
int b[2][n];
int c[3];
int d[n];
printf( "a, &a[0][0]= %p, %p\n", (void*)a, (void*)&a[0][0] );
printf( "b, &b[0][0]= %p, %p\n", (void*)b, (void*)&b[0][0] );
printf( "c, &c[0]= %p, %p\n", (void*)c, (void*)&c[0] );
printf( "d, &d[0]= %p, %p\n", (void*)d, (void*)&d[0] );
return 0;
}
=======================
--------------------
a, &a[0][0]= 2ff225d0, 2ff225d0
b, &b[0][0]= 2ff225b8, 2ff225e8
c, &c[0]= 2ff225f8, 2ff225f8
d, &d[0]= 2ff22598, 2ff22598
------------------------
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by Eric Sosma » Thu, 20 Apr 2006 03:12:31


XXXX@XXXXX.COM wrote On 04/18/06 13:51,:

Omitted here but present in the up-thread code:

#include <stdio.h>
static const int n=3;


Very strange. There's still a tiny sliver of doubt,
though, because "%p" produces an implementation-defined
representation. Unlikely as it seems, it's possible for
two equal-by-comparison pointers to convert to different
external representations. Just to remove that last, faint
possibility, could you augment your program to print the
results of direct comparisons, e.g.

printf ("a == &a[0][0]: %d\n",
(void*)a == (void*)&a[0][0]);

If any of these prints zero (as one seems quite likely to),
I think you've got solid evidence of a compiler bug.

Hmmm: One other oddball thought. What happens if you
execute all the printf()s again? Don't put 'em in a loop,
just copy and paste the entire group and execute them a
second time. I can imagine some kinds of compiler bug that
might cause the second group to print different output than
the first ...

--
XXXX@XXXXX.COM
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by shenki » Thu, 20 Apr 2006 03:26:26

No difference:

============================
#include <stdio.h>
static const int n=3;
int main( int narg, char *arg[] ) {
int a[2][3];
int b[2][n];
int c[3];
int d[n];

printf( "a, &a[0][0]= %p, %p\n", (void*)a, (void*)&a[0][0] );
printf( "b, &b[0][0]= %p, %p\n", (void*)b, (void*)&b[0][0] );
printf( "c, &c[0]= %p, %p\n", (void*)c, (void*)&c[0] );
printf( "d, &d[0]= %p, %p\n", (void*)d, (void*)&d[0] );

printf( "\n" );
printf( "a, &a[0][0]= %p, %p\n", (void*)a, (void*)&a[0][0] );
printf( "b, &b[0][0]= %p, %p\n", (void*)b, (void*)&b[0][0] );
printf( "c, &c[0]= %p, %p\n", (void*)c, (void*)&c[0] );
printf( "d, &d[0]= %p, %p\n", (void*)d, (void*)&d[0] );

printf( "\n" );
printf ( "a==&a[0][0]: %d\n", (void*)a == (void*)&a[0][0] );
printf ( "b==&b[0][0]: %d\n", (void*)b == (void*)&b[0][0] );
printf ( "c==&c[0]: %d\n", (void*)c == (void*)&c[0] );
printf ( "d==&d[0]: %d\n", (void*)d == (void*)&d[0] );

return 0;
}
============================

----------------------------
a, &a[0][0]= 2ff225d0, 2ff225d0
b, &b[0][0]= 2ff225b8, 2ff225e8
c, &c[0]= 2ff225f8, 2ff225f8
d, &d[0]= 2ff22598, 2ff22598

a, &a[0][0]= 2ff225d0, 2ff225d0
b, &b[0][0]= 2ff225b8, 2ff225e8
c, &c[0]= 2ff225f8, 2ff225f8
d, &d[0]= 2ff22598, 2ff22598

a==&a[0][0]: 1
b==&b[0][0]: 0
c==&c[0]: 1
d==&d[0]: 1
----------------------------
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by Eric Sosma » Thu, 20 Apr 2006 04:14:17


XXXX@XXXXX.COM wrote On 04/18/06 14:26,:

Looks like a compiler bug to me. Next step would
be to contact the compiler vendor with the information
you've gathered.

--
XXXX@XXXXX.COM
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by Douglas A. » Thu, 20 Apr 2006 05:17:28


b and &b[0[0] have different types and can in principle
have different representations. Even if they use the same
representation scheme, there can be multiple ways to
represent the same pointer value. And even if that isn't
a problem, %p doesn't have to produce identical output
for identical argument values (e.g. it could embed a
%p-usage-count sequence number, not that I would recommend
that).

The odds are pretty good on most platforms that you will
get identical outputs, but it's not something you should
rely on if portability is a goal.
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by shenki » Thu, 20 Apr 2006 05:33:16


Yes, of course. But I wanted to do a sanity check in this newsgroup
first.

Thanks for your help,
-P.
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by shenki » Thu, 20 Apr 2006 09:44:49

In fact, Doug, I think you're right, and that led me to another
experiment that makes me think that the implementation in question is
standard conforming after all.

Considering how you'd have to dereference b[0][0] using pointer
notation, I realized that you'd have to look at **b, not *b. Thus,
&b[0][0] had better compare equal not to b, as I had been assuming, but
rather to &b.

When I rewrote the program to test this, these did compare equal.

Comments welcome.

Live and learn,
-P.

==========================
#include <stdio.h>
static const int n=3;
int main( int narg, char *arg[] ) {
int a[2][3];
int b[2][n];
int c[3];
int d[n];

a[0][0] = b[0][0] = c[0] = d[0] =23;

printf( "\n" );
printf( "**a, a[0][0]= %d, %d\n", **a, a[0][0] );
printf( "**b, b[0][0]= %d, %d\n", **b, b[0][0] );
printf( "*c, c[0]= %d, %d\n", *c, c[0] );
printf( "*d, d[0]= %d, %d\n", *d, d[0] );

printf( "\n" );
printf ( "&a==&a[0][0]: %d\n", (void*)&a == (void*)&a[0][0] );
printf ( "&b==&b[0][0]: %d\n", (void*)&b == (void*)&b[0][0] );
printf ( "c==&c[0]: %d\n", (void*)&c == (void*)&c[0] );
printf ( "d==&d[0]: %d\n", (void*)&d == (void*)&d[0] );

printf( "\n" );
printf( "&a, &a[0][0]= %p, %p\n", (void*)&a, (void*)&a[0][0] );
printf( "&b, &b[0][0]= %p, %p\n", (void*)&b, (void*)&b[0][0] );
printf( "c, &c[0]= %p, %p\n", (void*)&c, (void*)&c[0] );
printf( "d, &d[0]= %p, %p\n", (void*)&d, (void*)&d[0] );

return 0;
}
====================

----------------------------------
**a, a[0][0]= 23, 23
**b, b[0][0]= 23, 23
*c, c[0]= 23, 23
*d, d[0]= 23, 23

&a==&a[0][0]: 1
&b==&b[0][0]: 1
c==&c[0]: 1
d==&d[0]: 1

&a, &a[0][0]= 2ff225d0, 2ff225d0
&b, &b[0][0]= 2ff225e8, 2ff225e8
c, &c[0]= 2ff225f8, 2ff225f8
d, &d[0]= 2ff22598, 2ff22598
------------------------------------------------------
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by shenki » Thu, 20 Apr 2006 10:05:12

Actually, I realize that my previous response to Doug is inconsistent
and incorrect. I think basically that he said it all. The only
requirement is that **b == b[0][0]. And it follows that &**b ==
&b[0][0]; but it does not then follow that *b == &b[0][0], which is
what I was mistakenly thinking.
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by Douglas A. » Fri, 21 Apr 2006 05:18:54

The simple fact is that a grate many C implementations use the same
numerical value for &b[0][0] and &b[0], even though the types are
not the same. printf of course knows nothing about the types (and
will in fact assume a void* representation for %p; on most platforms
with directly byte-addressable memory all object pointers have
identical representation and thus the printf call appears to work
even though it wasn't invoked with the proper argument types).
Again, these equivalencies occur on such platforms "by accident" and
are not guaranteed to occur for *every* conforming implementation of
C, so for portability reasons one should avoid relying upon them.
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by aegi » Mon, 15 May 2006 05:35:46


What is the chapter and verse in c99 that states that?
 
 
 

If b is a 2-D VLA, must it be true that b==&b[0][0]?

Post by Wojtek Ler » Mon, 15 May 2006 05:49:48


6.2.6.1#1 "The representations of all types are unspecified except as stated
in this subclause."