473,394 Members | 1,674 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Once again pointer to first element vs pointer to array cast topointer to element

I know that this topic has been discussed a lot, still I'd appreciate
a clear cut (and correct) answer:
I pass a multidimensional array to a function, which is defined as
int f(int a[10][10])
{
int *b=(void*)a;
int *c=a[0];
/*...*/
}
Now the questions come:
- Is it guaranteed that b and c points to the same object (or is this
implementation defined)?
- Is it always true that a[1][1] refers to the same object as c[11] ?
(There is no hole)
- Does dereferencing b violate any aliasing rule?

Thanks
Szabolcs
Jun 27 '08 #1
7 1666
Szabolcs Borsanyi wrote:
I know that this topic has been discussed a lot, still I'd appreciate
a clear cut (and correct) answer:
I pass a multidimensional array to a function, which is defined as
int f(int a[10][10])
{
int *b=(void*)a;
int *c=a[0];
/*...*/
}
Now the questions come:
- Is it guaranteed that b and c points to the same object (or is this
implementation defined)?
This is the only guarantee you have with that kind of conversion:
N869
6.3.2.3 Pointers

[#1] A pointer to void may be converted to or from a pointer
to any incomplete or object type. A pointer to any
incomplete or object type may be converted to a pointer to
void and back again; the result shall compare equal to the
original pointer.
- Is it always true that a[1][1] refers to the same object as c[11] ?
(There is no hole)
c[11] is undefined.
- Does dereferencing b violate any aliasing rule?

--
pete
Jun 27 '08 #2
On Tue, 6 May 2008 23:46:56 -0700 (PDT), Szabolcs Borsanyi
<bo******@thphys.uni-heidelberg.dewrote:
>I know that this topic has been discussed a lot, still I'd appreciate
a clear cut (and correct) answer:
I pass a multidimensional array to a function, which is defined as
int f(int a[10][10])
{
int *b=(void*)a;
int *c=a[0];
/*...*/
}
Now the questions come:
- Is it guaranteed that b and c points to the same object (or is this
implementation defined)?
It is true that a, a[0], and a[0][0] all start at the same address, to
be called THE ADDRESS below.

In your first assignment, the expression a is converted by the
compiler to the value and type of &a[0]. You then cast this to void*
and then implicitly convert it to an int*. Since the value (address)
is properly aligned for an int, everything is well defined and you end
with THE ADDRESS in the form of an int*.

In your second assignment, the expression a[0] is converted to the
value and type of &a[0][0] which is already an int* and assigned to an
int* with no conversion needed. You also end up with THE ADDRESS in
the form of an int*.

So b and c point to the same address and treat that address as the
address of an int. The answer to your question is yes they do and no
it is not implementation defined but a standard part of the language.
>- Is it always true that a[1][1] refers to the same object as c[11] ?
(There is no hole)
This is one for the language lawyers. Does c[11] (or even c[10])
exist from a purist point of view. There has been plenty of
discussion previously in this group. As a practical matter, I don't
believe anyone has identified a system where it doesn't work.
>- Does dereferencing b violate any aliasing rule?
Dereferencing b results in an int. Since b does in fact point to an
int there is no conflict. See section 6.5-7.
Remove del for email
Jun 27 '08 #3
On Tue, 6 May 2008 23:46:56 -0700 (PDT), Szabolcs Borsanyi
<bo******@thphys.uni-heidelberg.dewrote:
I know that this topic has been discussed a lot, still I'd appreciate
a clear cut (and correct) answer:
I pass a multidimensional array to a function, which is defined as
int f(int a[10][10])
Just to be clear, I assume you understand this actually declares a the
same type as int (*a) [10] . The C language allows you to pass e.g.
x[N][10] for any N (>0) as the argument to this parameter, and access
a[i][j] for i up to N and j up to 10 exclusive.
{
int *b=(void*)a;
int *c=a[0];
/*...*/
}
Now the questions come:
- Is it guaranteed that b and c points to the same object (or is this
implementation defined)?
They're guaranteed to point to the same (one) int. It is theoretically
arguable how many of the following int's they can access; see below.
- Is it always true that a[1][1] refers to the same object as c[11] ?
(There is no hole)
It is guaranteed there is no hole between array elements, at any
level; thus a[0][0] is followed immediately by a[0][1], and a[0] as a
whole is followed immediately by a[1] as a whole, therefore a[0][9] is
followed immediately by a[1][0].

And so it is guaranteed &a[0][10] == &a[1][0]. And, for example,
memcpy (tempi, (char*)a + 12*sizeof(int), sizeof(int))
will get you the value of a[1][2], and the reverse will set it.

According to the strict abstract semantics, you can't dereference
&a[0][10] and can't form &a[0][11] or higher at all. I believe that in
these strict abstract semantics the pointer you store into c _may_
retain this limitation, and thus c[10] and c[11] etc. might not work.
However, I don't know of, and to my knowledge no one has posted about,
any compiler that actually tries to do this. In practice, accessing 2D
(or higher) as 1D row-major works, and so much existing code assumes
this no sane C implementor will break it without very good reason.
- Does dereferencing b violate any aliasing rule?
*b for a[0][0] is definitely OK, but I assume you are actually
concerned with more like b[12]. As above, it's not absolutely clear
how much of a (or the argument e.g. x) you are strictly guaranteed
able to access through the 'voided' b. In practice it will be all.

- formerly david.thompson1 || achar(64) || worldnet.att.net
Jun 27 '08 #4
On May 19, 4:59 am, David Thompson <dave.thomps...@verizon.netwrote:
On Tue, 6 May 2008 23:46:56 -0700 (PDT), Szabolcs Borsanyi

<borsa...@thphys.uni-heidelberg.dewrote:
I know that this topic has been discussed a lot, still I'd appreciate
a clear cut (and correct) answer:
I pass a multidimensional array to a function, which is defined as
int f(int a[10][10])

Just to be clear, I assume you understand this actually declares a the
same type as int (*a) [10] . The C language allows you to pass e.g.
Your assumption is correct.
>
{
int *b=(void*)a;
int *c=a[0];
/*...*/
}
Now the questions come:
- Is it guaranteed that b and c points to the same object (or is this
implementation defined)?

They're guaranteed to point to the same (one) int. It is theoretically
arguable how many of the following int's they can access; see below.
- Is it always true that a[1][1] refers to the same object as c[11] ?
(There is no hole)

It is guaranteed there is no hole between array elements, at any
level; thus a[0][0] is followed immediately by a[0][1], and a[0] as a
whole is followed immediately by a[1] as a whole, therefore a[0][9] is
followed immediately by a[1][0].
Thanks, that's an important information. In covers that same statement
that is actually being discussed in an other thread subjected as
"Address of an array = address of its 1st".

So I am happy to learn that there may no be an array overhead (data
that belongs to the array and stored in the array before the first
element)
And so it is guaranteed &a[0][10] == &a[1][0]. And, for example,
memcpy (tempi, (char*)a + 12*sizeof(int), sizeof(int))
will get you the value of a[1][2], and the reverse will set it.
Good.
According to the strict abstract semantics, you can't dereference
&a[0][10] and can't form &a[0][11] or higher at all.
I think this statement of yours is in contradiction with the previous
one.
&a[0][10] is equivalent to a[0]+10. For those who forgot: a[0] is
an array of ten integers. That is why you say, *&a[0][10], or a[0][10]
is not correct. But in fact, here this array (a[0]) decays to a
pointer,
so &a[0][10] is &a[0][0]+10. From this you claimed that it compares
equal to &a[1][0], and if two pointers compare equal and are of the
same type, and one of them points to an object within its lifetime,
then
the other pointer points to the same object, and hence, it can also be
dereferenced.

Szabolcs
Jun 27 '08 #5
On Fri, May 23, 2008 at 12:14:42AM -0700, Szabolcs Borsanyi wrote:

I've cut a discussion about a in the body of
int f(int (*a)[10])
&a[0][10] is equivalent to a[0]+10. For those who forgot: a[0] is
an array of ten integers. That is why you say, *&a[0][10], or a[0][10]
is not correct. But in fact, here this array (a[0]) decays to a
pointer,
so &a[0][10] is &a[0][0]+10. From this you claimed that it compares
equal to &a[1][0], and if two pointers compare equal and are of the
same type, and one of them points to an object within its lifetime,
then
the other pointer points to the same object, and hence, it can also be
dereferenced.

Szabolcs
Here I have to correct myself.

C99 6.5.9:

6 Two pointers compare equal if and only if both are null pointers, both
are pointers to the same object (including a pointer to an object and a
subobject at its beginning) or function, both are pointers to one past the
last element of the same array object, or one is a pointer to one past the
end of one array object and the other is a pointer to the start of a
different array object that happens to immediately follow the first array
object in the address space.
------

So if two pointers are equal, and one of the points to an object,
they do not need to point to the same object.
Strange isn't it...

Szabolcs
Jun 27 '08 #6
Szabolcs Borsanyi <bo******@thphys.uni-heidelberg.dewrites:
On May 19, 4:59 am, David Thompson <dave.thomps...@verizon.netwrote:
<snip>
>It is guaranteed there is no hole between array elements, at any
level; thus a[0][0] is followed immediately by a[0][1], and a[0] as a
whole is followed immediately by a[1] as a whole, therefore a[0][9] is
followed immediately by a[1][0].

Thanks, that's an important information. In covers that same statement
that is actually being discussed in an other thread subjected as
"Address of an array = address of its 1st".
I think this is not quite the same thing. There two things involved:
one is that there are no holes, the other is that a pointer to the
whole object will compare equal (when suitably converted) to a pointer
to an initial sub-object. There are specific and separate guarantees
about both.
So I am happy to learn that there may no be an array overhead (data
that belongs to the array and stored in the array before the first
element)
>And so it is guaranteed &a[0][10] == &a[1][0]. And, for example,
memcpy (tempi, (char*)a + 12*sizeof(int), sizeof(int))
will get you the value of a[1][2], and the reverse will set it.

Good.
>According to the strict abstract semantics, you can't dereference
&a[0][10] and can't form &a[0][11] or higher at all.

I think this statement of yours is in contradiction with the previous
one.
No, there is no contradiction. The standard is worded to allow
a pointer (at least in some cases) to know its bounds, i.e., the
extent of the thing it points to. The conversion to, and access via,
a char * is specifically guaranteed. De-referencing the pointer
&a[0][10] and constructing &a[0][11] are not although, of course, the
behaviour is undefined so it is perfectly OK for it to work (as it
does on most implementations).
&a[0][10] is equivalent to a[0]+10. For those who forgot: a[0] is
an array of ten integers. That is why you say, *&a[0][10], or a[0][10]
is not correct. But in fact, here this array (a[0]) decays to a
pointer,
so &a[0][10] is &a[0][0]+10. From this you claimed that it compares
equal to &a[1][0], and if two pointers compare equal and are of the
same type, and one of them points to an object within its lifetime,
then
the other pointer points to the same object, and hence, it can also be
dereferenced.
That is not guaranteed. &a[0][10] can be constructed because it is a
"one past the end" pointer, but you can't de-reference it. Well, you
probably can, but it is UB to do so. You have to image two pointers
that compare equal because they discard the bounds information at that
point, but one can't be de-referenced because the bounds kick in.

--
Ben.
Jun 27 '08 #7
Szabolcs Borsanyi <s.********@sussex.ac.ukwrites:

<snip>
Here I have to correct myself.

C99 6.5.9:

6 Two pointers compare equal if and only if both are null pointers, both
are pointers to the same object (including a pointer to an object and a
subobject at its beginning) or function, both are pointers to one past the
last element of the same array object, or one is a pointer to one past the
end of one array object and the other is a pointer to the start of a
different array object that happens to immediately follow the first array
object in the address space.
------

So if two pointers are equal, and one of the points to an object,
they do not need to point to the same object.
Strange isn't it...
Yes. I think my previous reply may now be redundant. Sorry for the
noise.

--
Ben.
Jun 27 '08 #8

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

Similar topics

6
by: Irrwahn Grausewitz | last post by:
Hey, y'all. While doing some pointer experiments I encountered a problem. I know that I know the answer already, but trying to remember I just screwed up my mind. I wonder if someone would be...
4
by: Mantorok Redgormor | last post by:
I have a member of a struct which is: int32_t ut_addr_v6; And int32_t is typedef int int32_t; mentioning that for clarity. Now when I attempt the following: printf("%u.%u.%u.%u\n", ut_addr_v6,...
10
by: Kieran Simkin | last post by:
Hi, I wonder if anyone can help me, I've been headscratching for a few hours over this. Basically, I've defined a struct called cache_object: struct cache_object { char hostname; char ipaddr;...
2
by: Bruno van Dooren | last post by:
Hi All, i have some (3) different weird pointer problems that have me stumped. i suspect that the compiler behavior is correct because gcc shows the same results. ...
39
by: Martin Jørgensen | last post by:
Hi, I'm relatively new with C-programming and even though I've read about pointers and arrays many times, it's a topic that is a little confusing to me - at least at this moment: ---- 1)...
12
by: gcary | last post by:
I am having trouble figuring out how to declare a pointer to an array of structures and initializing the pointer with a value. I've looked at older posts in this group, and tried a solution that...
4
by: Christian Maier | last post by:
Hi After surfing a while I have still trouble with this array thing. I have the following function and recive a Segmentation fault, how must I code this right?? Thanks Christian Maier
7
by: lovecreatesbea... | last post by:
Is it always legal to cast expressions of type of multi-dimension array to type of pointer? Including: T to T* , T to T* , T to T* , and so on... For example: int *mtxrot1d(int *p,...
4
by: ctx2002 | last post by:
hi guys: I am reading Sqlite code at moment, my c language skill not good enough , hope some one here can help me. In function listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg);...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
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,...
0
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...
0
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,...
0
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...
0
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...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

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.