C
Chris Thomasson
Malcolm McLean said:Is this dodge legal?Chris Thomasson said:#include <stdio.h>
typedef char static_assert[
sizeof(long int) == sizeof(int) ? 1 : -1
];
Humm; I think so...
Malcolm McLean said:Is this dodge legal?Chris Thomasson said:#include <stdio.h>
typedef char static_assert[
sizeof(long int) == sizeof(int) ? 1 : -1
];
The declaration was
  int my_array[X];
[...]
*(&my_array + 1)
I thought this was a case where the last sentence of 6.5.6 p8 applies:
"If the result points one past the last element of the array object, it
shall not be used as the operand of a unary * operator that is
evaluated.". The "is evaluated" seems, to me, to reserved for the &*E
case where the validity of E is not significant. Surely the * "is
evaluated" in this case even though a decay to a pointer is the
immediate result?
____________________________________________________________
#include <stdio.h>
typedef char static_assert[
sizeof(long int) == sizeof(int) ? 1 : -1
];
typedef union foo_u {
long int a;
int b;
} foo;
int main(void) {
foo f = { 0 };
f.a = 1;
printf("%d\n", f.b);
return 0;
}
____________________________________________________________
Tomás Ó hÉilidhe said:Chris Thomasson:
____________________________________________________________
#include <stdio.h>
typedef char static_assert[
sizeof(long int) == sizeof(int) ? 1 : -1
];
typedef union foo_u {
long int a;
int b;
} foo;
int main(void) {
foo f = { 0 };
f.a = 1;
printf("%d\n", f.b);
return 0;
}
____________________________________________________________
You might want another static_assert to ensure that neither long int nor
int contain padding.
Ben Bacarisse said:I thought this was a case where the last sentence of
6.5.6 p8 applies:
"If the result points one past the last element of the
array object, it shall not be used as the operand of a
unary * operator that is evaluated.".
Peter Nilsson said:That's a new one I wasn't aware of! I've asked the
question in comp.std.c.
Chris Thomasson said:I have always wondered why that rule exists. For instance:
typedef union foo_u {
long int a;
int b;
} foo;
foo f = { 0 };
f.a = 1;
printf("%d\n", f.b);
Possibly because it is hard to write a rule which reliably forbids the
kind of union hacks which would break, but allows the ones that
wouldn't, while the kind of aliasing hackery which one can do with
unions is also done, and more reliably, with pointer aliasing. Using
your example, you could just as easily have made f a long int, and
called for &(int *)&f. Some would call that ugly, but then, what you're
doing _is_ slightly ugly, and the pointer code expresses more directly
what you're doing.
Richard Bos said:Possibly because it is hard to write a rule which reliably forbids the
kind of union hacks which would break, but allows the ones that
wouldn't,
Possibly because it is hard to write a rule which reliably forbids the
kind of union hacks which would break, but allows the ones that
wouldn't, while the kind of aliasing hackery which one can do with
unions is also done, and more reliably, with pointer aliasing.
user923005:
That void pointers have no stride, and yet you can do this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *p[5][5];
p[0][0] = NULL;
return 0;
}
"Have no stride"? As in "have no gait"? As in "don't have a particular way
of walking"?
Is this your way of saying you can't do pointer arithmetic on them?
[but the dereference in the latter nominally causes UB even if in[end_ptr] = my_array + sizeof my_array/sizeof*my_array;
[versus] = /* decay from */ * (&my_array+1);
sizeof myarray / sizeof *myarray also breaks in that case.I can't see anything wrong with:
int *pend = (void *)(&my_array + 1);
from a language point of view, but it is fragile in that it breaks
when the code moves to a function and my_array becomes a pointer.
David Thompson said:sizeof myarray / sizeof *myarray also breaks in that case.
You can put (void*)&array == (void*)array in somewhere to ensure it
really is an array and not a pointer
<type> *p = NULL; /* legal */
<type> *p = 0; /* legal */
<type> *p = '\0'; /* legal */
memset(p, 0, n); /* illegal! when p is misused to overwrite vales not
type char */
(Presumably this is not the same p just set to a null pointer. said:There is absolutely no guarantee that all bits 0 are a legal value for
all (except char, including pointer) types.
I don't think I'd say a _good_ chance; implementations that useAll bits 0 does NOT mean
that it is a nullpointer. An address (pointer) decays in 2 parts:
- address bits
- padding bits
So memset on anything, except char arrays, is always a good chance to
produce illegal padding bits.
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.