Kies Lee said:
main(void) {
union { char a[10];
int i;
} u;
int *p = (int*)&(u.a[1]);
*p = 17;
}
This would be expected to be quite slow, on current hardware platforms
which can make it work. Not that you would notice if you did it only
once. Besides, if it does "work," how can you check that it does the
same thing on all the platforms of interest to you? I suppose, for many
little-endian platforms, it would set u.a[1] to 17, and zero out
u.a[2..4]. The effect on u.i would depend on what was there before. On
a long-ago platform I learned on, it would (efficiently) zero out
u.a[0..2], and set u.a[3] and u.i to 17, without affecting u.a[4].
What's the point, other than to check how your platform behaves in odd
situations? You could do it more efficiently, portably, and readably,
with a simple assignment and a memset().
I don't want to know how it work, but I want to know why it works.
Because the address of the p(pointer) could be 3221217958(one possible
value),
it is not on the edge of the memory(cann't be divided by 4). I don't
know why ?
As far as the C language is concerned, what you're doing is invoking
undefined behavior. The standard doesn't say, and doesn't need to
say, anything more than that. The possible effects, as the standard
joke around here goes, include demons flying out of your nose.
The reason the authors of the C standard decided to make this
undefined behavior is that the actual result can differ widely on
different systems. It would have been possible to define a consistent
behavior and enforce it across all C implementations, but that would
have caused problems for some implementations. Instead, in certain
areas, each implementation is permitted to do whatever is most
natural, and leads to the most efficient code, for that particular
implementation.
If you have an odd address and try to read a 4-byte integer at that
address, one of several things can happen:
- You can get the full 4-byte integer from that address, if the
underlying hardware happens to support it. This might be slower
than for an aligned address, or it might not.
- You can get the full 4-byte integer from that address via some
kind of software support. For example, the attempt to read the
value can cause a system trap, and the memory management code in
the operating system can respond to the trap by reading the
value one byte at a time. This is likely to be much slower than
reading from an aligned address.
- You can get a full 4-byte integer, but not the one you were
expecting. I've worked with a system that simply ignores the
low-order bits of a misaligned address.
- You can get a system trap that crashes your program.
- You can get some other result that I haven't thought of.
Most of these things depend on the underlying hardware and/or
operating system. Any requirement for some particular behavior on
unaligned accesses would slow down *aligned* accesses on some systems,
making all programs slower.
For anything that the standard says is undefined behavior, you're
*never* guaranteed anything in particular; you can't assume that
you'll get a bus error, a segmentation fault, or anything else. The
system won't catch your error; it's entirely up to you to avoid making
the error in the first place.