S
Steve Kobes
Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
--Steve
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
--Steve
Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
--Steve
Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Yes it is legal and will print 4.
This array describes a contiguously allocated nonempty set of objects of
type int.
b = a[0] positions the int *b to the beginning of the array object as
would b = &a[0][0].
Chris said:Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Yes it is legal and will print 4.
I believe there are those in comp.std.c, at least, who will disagree
with you.
Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Yes it is legal and will print 4.
I believe there are those in comp.std.c, at least, who will disagree
with you.
Steve Kobes wrote:
Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Yes it is legal and will print 4.
I believe there are those in comp.std.c, at least, who will disagree
with you.
I could not follow your discussion which followed so I don't know
exactly which point I'm about to disagree with. Instead I will try to
present an argument that I believe shows the original question about
legality must be answered in the affirmative.
Barry said:Steve Kobes wrote:
Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Yes it is legal and will print 4.
I believe there are those in comp.std.c, at least, who will disagree
with you.
I could not follow your discussion which followed so I don't know
exactly which point I'm about to disagree with. Instead I will try to
present an argument that I believe shows the original question about
legality must be answered in the affirmative.
For an array q (not declared as a function parameter),
sizeof q / sizeof *q must evaluate to the number of elements in b.
For a pointer p to type T, the expression p+1 must evaluate to the
same value as (T*)((char*)p + sizeof(T))
Therefore
sizeof a must evaluate to the same value as 2*sizeof a[0]
sizeof a[0] and sizeof a[1] both must
evaluate to the same value as 2*sizeof a[0][0].
sizeof a[0][0] must evaluate to the same value as sizeof(int)
sizeof a must evaluate to the same value as 4*sizeof(int)
Since a contains 4 int and is exactly large enough to contain 4 int,
these 4 int must be located at b, b+1, b+2, and b+3.
pete said:Barry said:Steve Kobes wrote:
Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
I believe there are those in comp.std.c, at least, who will disagree
with you.
I could not follow your discussion which followed so I don't know
exactly which point I'm about to disagree with. Instead I will try to
present an argument that I believe shows the original question about
legality must be answered in the affirmative.
For an array q (not declared as a function parameter),
sizeof q / sizeof *q must evaluate to the number of elements in b.
For a pointer p to type T, the expression p+1 must evaluate to the
same value as (T*)((char*)p + sizeof(T))
Therefore
sizeof a must evaluate to the same value as 2*sizeof a[0]
sizeof a[0] and sizeof a[1] both must
evaluate to the same value as 2*sizeof a[0][0].
sizeof a[0][0] must evaluate to the same value as sizeof(int)
sizeof a must evaluate to the same value as 4*sizeof(int)
Since a contains 4 int and is exactly large enough to contain 4 int,
these 4 int must be located at b, b+1, b+2, and b+3.
The problem is that b, with (b = a[0])
is pointed at the first element of a two element array.
If you have
int a = 0, b = 0;
then, you can't do this
if (a + 1 == b) { /* The condition check is valid */
printf("%d\n", a[1]); /* Then printf call isn't valid */
}
Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
(snip argument which is based on the size of the objects, and 1-d array
arithmetic. ) The size argument is spurious. The compiler is allowed to
tell you the object is size 4, even if all 4 members were in separate
memory arrays in different solar systems. Theres no limit to the internal
magic the compiler can perform.
E. Robert Tisdale said:Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Despite the fact that this works everywhere,
neither C89 or C99 "guarantees" this.
You can reference *(b+0) and *(b+1) and
you can compute (b+2) but you can't reference *(b+2).
It isn't "legal" to compute (b+3) much less reference *(b+3).
If this "equivalence" is important to you,
I don't think that you need to be too concerned
about what the standard says.
Joe said:E. Robert Tisdale said:Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Despite the fact that this works everywhere,
neither C89 or C99 "guarantees" this.
You can reference *(b+0) and *(b+1) and
you can compute (b+2) but you can't reference *(b+2).
It isn't "legal" to compute (b+3) much less reference *(b+3).
If this "equivalence" is important to you,
I don't think that you need to be too concerned
about what the standard says.
Nonsense. b is an int* pointing to an array of four int's.
b[2] and b[3] are absolutely legal.
Joe said:E. Robert Tisdale said:Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Despite the fact that this works everywhere,
neither C89 or C99 "guarantees" this.
You can reference *(b+0) and *(b+1) and
you can compute (b+2) but you can't reference *(b+2).
It isn't "legal" to compute (b+3) much less reference *(b+3).
If this "equivalence" is important to you,
I don't think that you need to be too concerned
about what the standard says.
Nonsense. b is an int* pointing to an array of four int's.
b[2] and b[3] are absolutely legal.
Joe Wright said:E. Robert Tisdale said:Steve said:Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Despite the fact that this works everywhere,
neither C89 or C99 "guarantees" this.
You can reference *(b+0) and *(b+1) and
you can compute (b+2) but you can't reference *(b+2).
It isn't "legal" to compute (b+3) much less reference *(b+3).
If this "equivalence" is important to you,
I don't think that you need to be too concerned
about what the standard says.
Nonsense. b is an int* pointing to an array of four int's. b[2] and
b[3] are absolutely legal.
E. Robert Tisdale said:Joe said:E. Robert Tisdale said:Steve Kobes wrote:
Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Despite the fact that this works everywhere,
neither C89 or C99 "guarantees" this.
You can reference *(b+0) and *(b+1) and
you can compute (b+2) but you can't reference *(b+2).
It isn't "legal" to compute (b+3) much less reference *(b+3).
If this "equivalence" is important to you,
I don't think that you need to be too concerned
about what the standard says.
Nonsense. b is an int* pointing to an array of four int's.
b[2] and b[3] are absolutely legal.
James said:E. Robert Tisdale said:Joe said:E. Robert Tisdale wrote:
Steve Kobes wrote:
Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
There is special wording that allows any object,
including an array of arrays,
to be accessed completely using pointers to unsigned char.
This is what makes memcpy() usable.
However, for any other type this is an issue.
including an array of arrays,
to be accessed completely using pointers to unsigned char.
This is what makes memcpy() usable.
However, for any other type this is an issue.
If it was
int a[2][2] = {{1, 2}, {3, 4}}, *b = (int *)a;
^^^^^^^
instead,
there wouldn't be a problem accessing b[3], would there?
James said:E. Robert Tisdale said:Joe said:E. Robert Tisdale wrote:
Steve Kobes wrote:
Is this legal? Must it print 4?
int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
printf("%d\n", *(b + 3));
Despite the fact that this works everywhere,
neither C89 or C99 "guarantees" this.
You can reference *(b+0) and *(b+1) and
you can compute (b+2) but you can't reference *(b+2).
It isn't "legal" to compute (b+3) much less reference *(b+3).
If this "equivalence" is important to you,
I don't think that you need to be too concerned
about what the standard says.
Nonsense. b is an int* pointing to an array of four int's.
b[2] and b[3] are absolutely legal.
How can it point to such an array? None has been defined in this
program. C doesn't have multidimensional arrays, it has arrays of
arrays, and this is one of the subtle differences between those two
concepts. The named array 'a' contains two elements, which are
themselves arrays. The unnamed array identified by a[0] is an array of
only two elements, which are ints. The rules for the limits of pointer
arithmetic are defined in terms of arrays, and according to the rules of
the C language, 'a' is not an array of four integers.
The elements of the elements of 'a' must be stored in the same way as
the elements of an array of four integers. As a result, on most
implementations pf C code like this works exactly as you expect.
However, because this code has undefined behavior, an implementation is
free to implement pointers in such a fashion that it can keep track of
the limits beyond which they can't be dereferenced, and abort the
problem if those limits are violated. In particular, when a[0] decays to
a pointer, it's legal for the compiler to give that pointer
dereferencing limits of a[0] and a[0]+1.
There is special wording that allows any object, including an array of
arrays, to be accessed completely using pointers to unsigned char. This
is what makes memcpy() usable. However, for any other type this is an
issue.
Joe said:If I couldn't access a[1][0] as b[2] I would be surprised, and annoyed.
Michael said:There is special wording that allows any object,
including an array of arrays,
to be accessed completely using pointers to unsigned char.
This is what makes memcpy() usable.
However, for any other type this is an issue.
If it was
int a[2][2] = {{1, 2}, {3, 4}}, *b = (int *)a;
^^^^^^^
instead,
there wouldn't be a problem accessing b[3], would there?
There would. The same arguments hold.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.