Let's say I have:
int a[20] = {0};
Is the declaration below legal according to C89?
int (*p)[5] = (int (*)[5])(a+6);
Mohan
consider this program:-
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int (*p)[5] = (int(*)[5])(a+6);
printf("\n %d",(*p)[0]);
return(EXIT_SUCCESS);
}
compile this program as gcc -g -ansi -pedantic -o progname
progname.c , then decide for yourself
> As far as i think (i am not 100% certain though) its legal. But in
> this case only (p+2)[3] can be safely addressed for storing values.
what do you mean by the statement that (p+2)[3] can be safely
addressed for storing values. ???
well i meant that the last value accessible through p is (p+2)[3] it
should be the value at a[19].
Yes, gcc doesn't give any warnings, but we are casting p to what we
want. If we remove the cast, gcc does give a warning saying:
"initialization from incompatible pointer type". I understand that the
initialization is from an incompatible pointer type, so I *think* this
means that the behavior is undefined. But I am not sure.
Thanks,
Alok
> On Dec 16, 12:25 am, annalissa <aark...@gmail.com> wrote:
>> On Dec 15, 12:24 pm, mohangupta13 <mohangupt...@gmail.com> wrote:
>>
>> > On Dec 15, 4:03 pm, Alok Singhal <gandalf...@gmail.com> wrote:> Hi,
>>
>> > > Let's say I have:
>>
>> > > int a[20] = {0};
>>
>> > > Is the declaration below legal according to C89?
>>
>> > > int (*p)[5] = (int (*)[5])(a+6);
<snip>
>> > As far as i think (i am not 100% certain though) its legal.
"Legal" is an odd word in this context. The conversion between the
two pointer types is implementation defined so I suppose pretty much
any result is possible though there is an "obvious" conversion.
>> > But in
>> > this case only (p+2)[3] can be safely addressed for storing values.
>>
>> what do you mean by the statement that (p+2)[3] can be safely
>> addressed for storing values. ???
>
> well i meant that the last value accessible through p is (p+2)[3] it
> should be the value at a[19].
(p+2)[3] and a[19] have different types. You probably meant
(*(p+2))[3] but that is simpler to right as p[2][3].
--
Ben.
Think again. The purpose of the cast is not to silence the warning
but to coerce the value of the expression to a compatible type and
eliminate the condition that requires a diagnostic.
The code
unsigned char *ptr = (unsigned char*)(a+6);
will produce the exact same warning without the cast yet the
initialization is perfectly well defined as written.
--
Remove del for email
Depends on wheather a+6 is properly aligned for an int(*)[5].
If not, then no, it's not valid. I don't believe the standard
guarantees you can dereference it, only convert it back to an
int *. Also, you are accessing part of an object using a
different type to the effective type.
> consider this program:-
<snip>
>
> compile this program as gcc -g -ansi -pedantic -o progname
> progname.c , then decide for yourself
That something compiles without a diagnostic under gcc does not
mean it is correct. E.g. ...
int main(void) { return * (int *) 0; }
--
Peter
what is the diagnostic that i am missing ..??
Thanks. This is what I was looking for. I should have read the standard
more carefully as well. So 6.3.2.3p7 (N1336) applies here:
A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the resulting
pointer is not correctly aligned for the pointed-to type, the behavior
is undefined. Otherwise, when converted back again, the result shall
compare equal to the original pointer.
There is no guarantee that int (*)[5] is correctly aligned for int *, and
even if it is, the standard makes no guarantees about dereferencing such
a pointer.
-Alok
Do you just invent these assumptions or do you read them somewhere
that we can tell others to avoid?
int array[5] = {2};
int (*ptr_a)[5] = &array;
int *ptr_i = array;
Is there any doubt in your mind that both pointers point to the same
address in memory? Is there any doubt that the expression
(unsigned char*)ptr_a == (unsigned char*)ptr_i
will evaluate to 1.
Is there any doubt in your mind that ptr_i[0] references the first
element of the array and evaluates to 2 while ptr_i[1] references the
second element and evaluates to 0?
Is there any doubt in your mind ptr_a[0][0] and ptr_a[0][1] reference
the exact same objects and hence must evaluate to the same values?
There is no diagnostic required but the code invokes undefined
behavior.
<snip>
>>Thanks. This is what I was looking for. I should have read the
>>standard more carefully as well. So 6.3.2.3p7 (N1336) applies here:
>>
>> A pointer to an object or incomplete type may be converted to a
>> pointer to a different object or incomplete type. If the resulting
>> pointer is not correctly aligned for the pointed-to type, the behavior
>> is undefined. Otherwise, when converted back again, the result shall
>> compare equal to the original pointer.
>>
>>There is no guarantee that int (*)[5] is correctly aligned for int *,
>>and even if it is, the standard makes no guarantees about dereferencing
>>such a pointer.
>
> Do you just invent these assumptions or do you read them somewhere that
> we can tell others to avoid?
Please bear with me while I try to explain myself. Isn't there a
difference between:
int array[5] = {2};
int (*ptr)[5] = &array;
and:
int array[20] = {2};
int (*ptr)[5] = (int (*)[5])(array + 6);
In the second snippet, "array + 6" is of type "pointer to int". In the
first snippet, "&array" is of type "int (*)[5]". So, if I understand
correctly, and I think that is what you're saying too: the first snippet
is well-defined by the standard, while the result second snippet, in
particular the assignment to "ptr" is implementation-defined.
So, *if I understand correctly*, in the second snippet above:
- the cast is needed because it coerces "a+6" to the correct type for
"ptr".
- if "ptr" is a pointer to (signed or unsigned) char, or any other type
that is correctly aligned for the type of "a+6" (int *), the
initialization is well-defined in that I can convert "ptr" back to
int * and get the same value.
- if "ptr" isn't correctly aligned for int *, the result of the
initialization is implementation-defined.
Please let me know where I am wrong in my assumptions.
> int array[5] = {2};
> int (*ptr_a)[5] = &array;
> int *ptr_i = array;
>
> Is there any doubt in your mind that both pointers point to the same
> address in memory? Is there any doubt that the expression
> (unsigned char*)ptr_a == (unsigned char*)ptr_i
> will evaluate to 1.
>
> Is there any doubt in your mind that ptr_i[0] references the first
> element of the array and evaluates to 2 while ptr_i[1] references the
> second element and evaluates to 0?
>
> Is there any doubt in your mind ptr_a[0][0] and ptr_a[0][1] reference
> the exact same objects and hence must evaluate to the same values?
The answer to all the above questions is, "no". I agree with all the
statements above.
Thanks again for your help,
-Alok
If the value a+6 is correctly aligned for the type int(*)[5], then
your initialization of ptr is well defined. If not, the
initialization invokes undefined behavior (6.3.2.3-7), not
implementation defined behavior. So the question revolves around
whether a+6 is properly aligned.
Consider the definition
int x[sizeof(int)][5];
We know that each element x[i][j] occupies exactly sizeof(int) bytes.
Further more, each element x[i][j+1] starts exactly sizeof(int) bytes
beyond the start of the previous element x[i][j] (except for the
obvious boundary condition when j==4).
We also know that each x[i] is an array of 5 int and that x[i+1]
starts exactly 5*sizeof(int) bytes beyond the start of x[i] (again
except for the boundary condition when i==sizeof(int)-1).
Because sizeof(int) is not a factor of 5, I assert the x[i] as a group
completely exhaust all possible alignments for int[5] and that they
also completely exhaust all possible alignments for int. (I don't
remember what the branch of mathematics is called that is used to
prove these assertions but if you choose both common (2, 4, and 8) and
off-the-wall (3, 15 23) values for sizeof(int) and work out the
addresses you should be convinced.) Consequently, the value a+6 will
exactly match the alignment of at least one of the x[i] and is
therefore properly aligned.
>
>Please let me know where I am wrong in my assumptions.
>
--
Remove del for email
I have no idea why you think sizeof(int) should be used here!
> We know that each element x[i][j] occupies exactly sizeof(int)
> bytes. Further more, each element x[i][j+1] starts exactly
> sizeof(int) bytes beyond the start of the previous element
> x[i][j] (except for the obvious boundary condition when j==4).
>
> We also know that each x[i] is an array of 5 int and that
> x[i+1] starts exactly 5*sizeof(int) bytes beyond the start
> of x[i] (again except for the boundary condition when i==
> sizeof(int)-1).
>
> Because sizeof(int) is not a factor of 5,
Not commonly, but on the virtual machine it may be.
> I assert the x[i] as a group completely exhaust all possible
> alignments for int[5] and that they also completely exhaust
> all possible alignments for int. ...
I've had a previous discussion considering something like...
int a[7];
int (*p)[2] = (int (*)[2]) (a + 1);
The problem is whether int(*)[2] can have a stricter
alignement than int *. I think it can! I can't see anything
in the standard that says a pointer to an element of an array
of N elements will always be properly aligned for a pointer
to an array of M elements if M < N.
Why should it? Look at an example using structs...
struct int_pair_t { int a; int b; };
int a[7];
struct int_pair_t *p = (struct int_pair_t *) (a + 1);
Even if one shows that there is no padding in the struct,
there is still no guarantee that a + 1 is properly aligned
for a struct int_pair_t *.
Simple question: Is there anything precluding an
implementation giving struct int_pair_t a stricter
alignment than int?
[This is ignoring the issue of effective type which plays
a further role in the discussion.]
--
Peter
>Barry Schwarz <schwa...@dqel.com> wrote:
>> Alok Singhal
>> > Please bear with me while I try to explain myself. Isn't
>> > there a difference between:
>> >
>> > int array[5] = {2};
>> > int (*ptr)[5] = &array;
>> >
>> > and:
>> >
>> > int array[20] = {2};
>> > int (*ptr)[5] = (int (*)[5])(array + 6);
>>
>> ...the question revolves around whether a+6 is properly aligned.
>>
>> Consider the definition
>> int x[sizeof(int)][5];
>
>I have no idea why you think sizeof(int) should be used here!
I thought it would insure exhaustion but, as you point out below, it
works only for currently common implementations and fails in the
perverse case.
>
>> We know that each element x[i][j] occupies exactly sizeof(int)
>> bytes. Further more, each element x[i][j+1] starts exactly
>> sizeof(int) bytes beyond the start of the previous element
>> x[i][j] (except for the obvious boundary condition when j==4).
>>
>> We also know that each x[i] is an array of 5 int and that
>> x[i+1] starts exactly 5*sizeof(int) bytes beyond the start
>> of x[i] (again except for the boundary condition when i==
>> sizeof(int)-1).
>>
>> Because sizeof(int) is not a factor of 5,
>
>Not commonly, but on the virtual machine it may be.
>
>> I assert the x[i] as a group completely exhaust all possible
>> alignments for int[5] and that they also completely exhaust
>> all possible alignments for int. ...
>
>I've had a previous discussion considering something like...
>
> int a[7];
> int (*p)[2] = (int (*)[2]) (a + 1);
>
>The problem is whether int(*)[2] can have a stricter
>alignement than int *. I think it can! I can't see anything
>in the standard that says a pointer to an element of an array
>of N elements will always be properly aligned for a pointer
>to an array of M elements if M < N.
Yes. If the dimension of the array pointed to is a factor of
sizeof(int), then my argument fails. For example, if sizeof(int) is 4
and the alignment for int[2] is 8, then obviously a+1 or a+2 must be
misaligned for p.
Applying this to the specific example under consideration where the
dimension is 5, this can happen only if the alignment for an int[5] is
a multiple of 5*sizeof(int), such as 20 to match the example. In such
a case, array+6 may or may not be properly aligned but if it is then
array+7 is definitely not.
So to the OP I apologize for the error in my response. It is probably
properly aligned on all current systems you are likely to run on but
it may very well invoke undefined behavior on the DS9K or some new
system where the alignment of int[5] is more restrictive than that of
int.
>
>Why should it? Look at an example using structs...
>
> struct int_pair_t { int a; int b; };
> int a[7];
> struct int_pair_t *p = (struct int_pair_t *) (a + 1);
>
>Even if one shows that there is no padding in the struct,
>there is still no guarantee that a + 1 is properly aligned
>for a struct int_pair_t *.
>
>Simple question: Is there anything precluding an
>implementation giving struct int_pair_t a stricter
>alignment than int?
>
>[This is ignoring the issue of effective type which plays
>a further role in the discussion.]
--
Remove del for email
Yes, I think I wasn't clear enough in my posts so far. This indeed
was my question to begin with.
> Consider the definition
> int x[sizeof(int)][5];
>
> We know that each element x[i][j] occupies exactly sizeof(int) bytes.
> Further more, each element x[i][j+1] starts exactly sizeof(int) bytes
> beyond the start of the previous element x[i][j] (except for the
> obvious boundary condition when j==4).
>
> We also know that each x[i] is an array of 5 int and that x[i+1]
> starts exactly 5*sizeof(int) bytes beyond the start of x[i] (again
> except for the boundary condition when i==sizeof(int)-1).
>
> Because sizeof(int) is not a factor of 5, I assert the x[i] as a group
> completely exhaust all possible alignments for int[5] and that they
> also completely exhaust all possible alignments for int. (I don't
> remember what the branch of mathematics is called that is used to
> prove these assertions but if you choose both common (2, 4, and 8) and
> off-the-wall (3, 15 23) values for sizeof(int) and work out the
> addresses you should be convinced.) Consequently, the value a+6 will
> exactly match the alignment of at least one of the x[i] and is
> therefore properly aligned.
OK. I see. I can agree with your arguments. But sizeof(int) can be a
factor of 5 theoretically, and the number 5 in my original post is
something I picked out of convenience. In general, it could be any
number (2, 8, 4, whatever). Similarly, the same goes for the numbers
and 6, and 20 in my original post. So, given
int a[N] = {0};
int (*p)[m] = (int (*)[m])(a+k);
with N, m, k as integers (and k+m < N of course), I can't be sure if a
+k is properly aligned for int (*)[m]?
Thanks a lot for your responses!
-Alok
No need for the apology - I learned quite a lot from your and Peter's
answers, and I should have been more specific to begin with. After
all these years of lurking here in clc, I thought I was ready to post
an interesting question (interesting to me anyway). :-)
-Alok
I am pretty sure arrays don't actually have alignment requirements,
only the objects in them.
> Why should it? Look at an example using structs...
>
> struct int_pair_t { int a; int b; };
> int a[7];
> struct int_pair_t *p = (struct int_pair_t *) (a + 1);
>
> Even if one shows that there is no padding in the struct,
> there is still no guarantee that a + 1 is properly aligned
> for a struct int_pair_t *.
For a struct, this might be true. For an array, it's not.
> Simple question: Is there anything precluding an
> implementation giving struct int_pair_t a stricter
> alignment than int?
I'm not sure. I think in practice you probably can't, because you can
set up an elaborate construct involving unions which allows you to prove
that you have to be able to treat a pointer to a large enough hunk of
space which is aligned properly for an int as a pointer to the first member
of the structure.
But structs are not the same thing as arrays. I am pretty sure that
array-of-foo has to have the same alignment requirements as foo, because
any foo can be treated as an array of 1 foo, and you can treat any pointer
to foo as an array of foo. Basically, the wording guaranteeing that
the offset in bytes of foo[1] is precisely sizeof(foo[0]) covers it.
So I'm pretty sure that arrays can't have alignment requirements more
restrictive than the alignment requirements of the things they're arrays
of.
-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I'd like to think that's true, but I'm not entirely convinced unless
it can be proven from the standard.
>> Simple question: Is there anything precluding an
>> implementation giving struct int_pair_t a stricter
>> alignment than int?
>
> I'm not sure. I think in practice you probably can't, because you can
> set up an elaborate construct involving unions which allows you to prove
> that you have to be able to treat a pointer to a large enough hunk of
> space which is aligned properly for an int as a pointer to the first member
> of the structure.
>
> But structs are not the same thing as arrays. I am pretty sure that
> array-of-foo has to have the same alignment requirements as foo, because
> any foo can be treated as an array of 1 foo, and you can treat any pointer
> to foo as an array of foo. Basically, the wording guaranteeing that
> the offset in bytes of foo[1] is precisely sizeof(foo[0]) covers it.
Yes, but it doesn't follow from that that an array type can't have
a stricter alignment requirement than its element type.
> So I'm pretty sure that arrays can't have alignment requirements more
> restrictive than the alignment requirements of the things they're arrays
> of.
Consider a hypothetical implementation in which int is 4 bytes (32
bits), and the CPU has instructions that can access 4-byte and 8-byte
objects in memory, but only if they're 4-byte or 8-byte aligned.
The implementation imposes a 4-byte alignment requirement on int
objects. It also imposes an 8-byte alignment on int[N] objects,
where N is even. (The question is whether the latter requirement
is allowed.)
I declare an arr of int:
int arr2[4];
Each element is 4-byte aligned. The object as a whole is 8-byte
aligned.
For most operations, everything works just as you'd expect. The
question is whether this:
typedef int pair[2];
pair *p = (pair*)&arr2[1];
is valid, or whether operations on p can invoke undefined behavior
because of the alignment mismatch.
If an implementation causes the initialization of p to trap, for
example, what clause of the standard does the implementation violate?
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
There is no guarantee that (a+6) is correctly aligned for int (*)[5],
but if it is then since it does point to an object that is suitably
composed to be one (or two) array(s) of (int[5]), and since both the
element types are (int), dereferencing it will work fine.
> On 2009-12-18, Peter Nilsson <ai...@acay.com.au> wrote:
>> The problem is whether int(*)[2] can have a stricter
>> alignement than int *. I think it can! I can't see anything
>> in the standard that says a pointer to an element of an array
>> of N elements will always be properly aligned for a pointer
>> to an array of M elements if M < N.
>
> I am pretty sure arrays don't actually have alignment requirements,
> only the objects in them.
The Standard seems to allow the possibility that arrays of fixed
length (and having more than one element) have different
alignment requirements than arrays with one element (or
equivalently, than arrays of unknown length). 6.2.5p13 says:
Each complex type has the same representation and alignment
requirements as an array type containing exactly two elements of
the corresponding real type; the first element is equal to the
real part, and the second element to the imaginary part, of the
complex number.
It seems strange to mention the "alignment requirements [of] an
array type containing exactly two elements" if that had to be
the same as the alignment requirement of the element type.
>> Why should it? Look at an example using structs...
>>
>> struct int_pair_t { int a; int b; };
>> int a[7];
>> struct int_pair_t *p = (struct int_pair_t *) (a + 1);
>>
>> Even if one shows that there is no padding in the struct,
>> there is still no guarantee that a + 1 is properly aligned
>> for a struct int_pair_t *.
>
> For a struct, this might be true. For an array, it's not.
>
>> Simple question: Is there anything precluding an
>> implementation giving struct int_pair_t a stricter
>> alignment than int?
>
> I'm not sure. I think in practice you probably can't, because you can
> set up an elaborate construct involving unions which allows you to prove
> that you have to be able to treat a pointer to a large enough hunk of
> space which is aligned properly for an int as a pointer to the first member
> of the structure.
Certainly it can. Nothing preventing all structs from being
multiples of 32 bytes in length, for example, and always aligned
on a 32 byte boundary.
> But structs are not the same thing as arrays. I am pretty sure that
> array-of-foo has to have the same alignment requirements as foo, because
> any foo can be treated as an array of 1 foo, and you can treat any pointer
> to foo as an array of foo. Basically, the wording guaranteeing that
> the offset in bytes of foo[1] is precisely sizeof(foo[0]) covers it.
Any array can be treated as through an array type (T(*)[1]), but
not the other direction.
> So I'm pretty sure that arrays can't have alignment requirements more
> restrictive than the alignment requirements of the things they're arrays
> of.
For arrays of length 1, yes; for arrays of length 2 or more,
their alignments can be more restrictive.
<snip>
> The Standard seems to allow the possibility that arrays of fixed
> length (and having more than one element) have different
> alignment requirements than arrays with one element (or
> equivalently, than arrays of unknown length). 6.2.5p13 says:
>
> Each complex type has the same representation and alignment
> requirements as an array type containing exactly two elements of
> the corresponding real type; the first element is equal to the
> real part, and the second element to the imaginary part, of the
> complex number.
>
> It seems strange to mention the "alignment requirements [of] an
> array type containing exactly two elements" if that had to be
> the same as the alignment requirement of the element type.
It does seem strange. Without consulting the Standard in detail, I
wouldn't want to express an opinion on its requirements on the alignment
of arrays, but your point is a good one. In the absence of information
to the contrary, this seems to be an example of the exception proving
the rule. That is, there would be no need to mention an exception to the
rule if there weren't a rule!
(Parallel example: "no parking between 8am and 6pm" strongly suggests
that parking at other times is okay.)
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
> Seebs <usenet...@seebs.net> writes:
>
> > On 2009-12-18, Peter Nilsson <ai...@acay.com.au> wrote:
> >> The problem is whether int(*)[2] can have a stricter
> >> alignement than int *. I think it can! I can't see anything
> >> in the standard that says a pointer to an element of an array
> >> of N elements will always be properly aligned for a pointer
> >> to an array of M elements if M < N.
> >
> > I am pretty sure arrays don't actually have alignment requirements,
> > only the objects in them.
>
> The Standard seems to allow the possibility that arrays of fixed
> length (and having more than one element) have different
> alignment requirements than arrays with one element (or
> equivalently, than arrays of unknown length). 6.2.5p13 says:
> <snip>
And footnote 106 to 6.7.2.1p16 on flexible array members (of a struct)
says so explicitly (though not formally normative).
That said, I've never heard of any machine which makes them different.
I DO know of machines where at least sometimes array of T is aligned
stricter than scalar T -- but all array of given T regardless of the
bound. Does anyone know (and willing to say) an actual example?
> On Tue, 12 Jan 2010 18:10:12 -0800, Tim Rentsch
> <t...@alumni.caltech.edu> wrote:
>
>> Seebs <usenet...@seebs.net> writes:
>>
>> > On 2009-12-18, Peter Nilsson <ai...@acay.com.au> wrote:
>> >> The problem is whether int(*)[2] can have a stricter
>> >> alignement than int *. I think it can! I can't see anything
>> >> in the standard that says a pointer to an element of an array
>> >> of N elements will always be properly aligned for a pointer
>> >> to an array of M elements if M < N.
>> >
>> > I am pretty sure arrays don't actually have alignment requirements,
>> > only the objects in them.
>>
>> The Standard seems to allow the possibility that arrays of fixed
>> length (and having more than one element) have different
>> alignment requirements than arrays with one element (or
>> equivalently, than arrays of unknown length). 6.2.5p13 says:
>> <snip>
>
> And footnote 106 to 6.7.2.1p16 on flexible array members (of a struct)
> says so explicitly (though not formally normative).
I scratched my head when I saw this comment, and wondered why I'd
never noticed this footnote before. As it turns out, the
footnote was there in C99 but actually ended up being taken out
as part of TC1 or TC2, and so it isn't there in either N1124 or
N1256 (N1256 being the version that I use most often, because
it's the one I have electronically indexed).
> That said, I've never heard of any machine which makes them different.
> I DO know of machines where at least sometimes array of T is aligned
> stricter than scalar T -- but all array of given T regardless of the
> bound. Does anyone know (and willing to say) an actual example?
Where it's likely to come up is in numeric (especially floating
point?) vectors of short lengths (especially powers of two) that
match some sort of SIMD capability. More specifically, some of
the more exotic GPU's (about which I know very little), might be
helped by choosing a more restrictive alignment for such vectors.
The footnote was dropped in TC2:
21. Page 103 6.7.2.1
In paragraph 16, remove footnote 106.
in response to DR #282,
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_282.htm>.