memory alignment

S

sachin_mzn

Hi,
What is the concept of memory alignment?
Is memory alignment differs, If a data type is local to a function or
if it is a member of structure or union?
How 32 to 64 bit processor afftects the memory alignment?
 
M

Mac

Hi,
What is the concept of memory alignment?
Is memory alignment differs, If a data type is local to a function or
if it is a member of structure or union?
How 32 to 64 bit processor afftects the memory alignment?

Normally, memory is aligned correctly and you don't have to worry about
it. For example, if you use malloc() or related functions, the memory will
be aligned for any type.

However, if you access data through a pointer to a different type (I have
not had to do this in my code, but I suppose it could happen), then you
could have a problem with memory alignment. I believe it is only a problem
when you cast from a pointer to a larger type to a pointer to a smaller
type.

Here is an example of code which might cause alignment problems on real
platforms:

double *foo;

....

foo = malloc(20 * sizeof *foo);
foo = 1 + (unsigned char *)foo;
*foo = 0.0;

Oops.

I think you can see where the alignment problem occurred.

HTH

--Mac
 
I

infobahn

Hi,
What is the concept of memory alignment?

Computers sometimes find it convenient to grab things in N-byte chunks,
where N is > 1. It's by no means uncommon for, say, ints to occupy
more than 1 byte of memory.

These computers often find it extremely convenient indeed if these
N-byte chunks are stored at addresses that are an exact multiple of N.

That's "alignment" in a nutshell. Like all nutshells, it doesn't
leave much room for pedantry, so expect a nutcracker real soon now.
Is memory alignment differs, If a data type is local to a function or
if it is a member of structure or union?

I don't see why it should.
How 32 to 64 bit processor afftects the memory alignment?

Insert N here.
 
S

sachin_mzn

but what KR mentioned that it is safer to cast a larger data type
pointer into a smaller one.
But the vice versa is dangerous.
e.g. char is the smallest data type available , so pointer to every
data type can be casted
to char*. please point me if I i am wrong.

and in above snippet why we need to add 1 in statement foo = 1 +
(unsigned char *)foo;
..


Regards,
Sachin
 
J

Jack Klein

Hi,
What is the concept of memory alignment?

The mechanism of memory alignment is not defined by the C language
standard, the standard merely allows an implementation to require it
and states that a program violating it causes undefined behavior.

In almost all cases, alignment is used to place an object of n-bytes
on an address that is either a multiple of n or a multiple of the
memory bus width of the processor, whichever is less.

Some processors dedicate extra circuitry to handling data that is not
properly aligned. Consider a processor with 8-bit bytes where type
int has 32 bits and the processor has a 32-bit path to memory. If an
int is located at address divisible by 4, the processor can read or
write all 32 bits in a single memory cycle. If the address is not
divisible by 4, it would have to perform two reads or writes to put
part of the int into two different 32-bit blocks. This causes the
program to execute more slowly, in some cases drastically so.

Other processors do not dedicate circuitry to automatically handle
misaligned data. Some ignore the lowest bits of the address and
therefore read or write something other than what the programmer
intended. Others generate hardware traps when a misaligned memory
access happens, that typically causes the operating system to shut
down the program.
Is memory alignment differs, If a data type is local to a function or
if it is a member of structure or union?

The C standard does not define this, but most likely these factors
make no difference.
How 32 to 64 bit processor afftects the memory alignment?

It doesn't have anything in particular to do with the word size of the
processor. It has to do with the issues above, which are largely
independent of word size.
 
J

Jack Klein

On 27 Dec 2004 00:15:28 -0800, (e-mail address removed) wrote in
comp.lang.c:

Please quote some context from the message you are responding to. In
this case, that particular message has not shown up on my server, so I
can't even see what you are talking about.
but what KR mentioned that it is safer to cast a larger data type
pointer into a smaller one.

No, it is safe to cast a pointer to some data type to a pointer to
another type that has the same or a less strict alignment requirement.
That might be a "larger" to "smaller" relationship, but then again it
might not.
But the vice versa is dangerous.
e.g. char is the smallest data type available , so pointer to every
data type can be casted
to char*. please point me if I i am wrong.

Yes, a pointer to char can point to every single byte addressable in a
C program. Therefore it can point to every single byte of every
object, including the first byte. Also pointer to void is required to
have exactly the same representation as pointer to char.
and in above snippet why we need to add 1 in statement foo = 1 +
(unsigned char *)foo;

There is no snippet above. In general, don't cast pointers from one
type to another type unless you have a very good reason to do so, and
unless you know what you are doing.

99% of the pointer casts in typical C code are not necessary and make
the code non-portable for no good reason.
 
T

Tim Prince

In a currently common case, the 64-bit code uses 64-bit int and pointer
instructions, which work faster if the data are aligned. The 32-bit
predecessor had no 64-bit pointers, and 64-bit int operations were
synthesized from 32-bit operations. Thus, you would require 64-bit
alignment to get full benefit of the 64-bit int instructions, where it did
not matter with the 32-bit instructions. For 64-bit doubles and the like,
the 32-bit CPU had the same 64-bit alignment requirement for performance, as
well as 128-bit alignment requirement for wider types.
 
E

Eric Sosman

Jack said:
In almost all cases, alignment is used to place an object of n-bytes
on an address that is either a multiple of n or a multiple of the
memory bus width of the processor, whichever is less. [...]

Since arrays are contiguous (no padding between elements),
two adjacent elements of an array of Anytype objects begin
sizeof(Anytype) bytes apart. If an array is properly aligned,
all its elements are properly aligned, too. Therefore, the
alignment requirement for an Anytype object is a divisor of
sizeof(Anytype) -- perhaps 1, perhaps sizeof(Anytype) itself,
or perhaps something in between.

Note that two types of the same size might have different
alignment requirements (as far as C is concerned, anyway). For
example, imagine an integer-only ALU with permissive alignment
constraints coupled with a floating-point coprocessor that
requires strictly-aligned operands: you might have sizeof(int)
equal to sizeof(float) on a machine that requires four-byte
alignment for floats but allows ints to reside "anywhere."
 
J

Jonathan Bartlett

Hi,
What is the concept of memory alignment?

Memory alignment is based on how the CPU addresses memory. For example,
let's say your CPU loads memory, say, 4 bytes at a time from addresses
that are a multiple of four. Therefore, if you access 4 bytes from
memory address 4, the CPU will load memory addresses 4,5,6, and 7 all at
once in a single operation. However, if you access 4 bytes from memory
address 5, the CPU will take two operations: one to load from 4,5,6, and
7, and another to load from 8,9,10, and 11. It will then have to shift
the bytes around into their proper position. So, if your data is not
aligned on the same lines as your CPU's memory access, it can take quite
a bit longer for the CPU to grab data for you.
> Is memory alignment differs, If a data type is local to a function or
> if it is a member of structure or union?

Same concepts. Many C compilers will pad your structures so that each
piece of data is aligned, assuming that the structure itself starts on
an aligned piece of memory.
> How 32 to 64 bit processor afftects the memory alignment?

It's actually the address bus that makes the big difference.

Jon
 
E

Eric Sosman

Jonathan said:
Memory alignment is based on how the CPU addresses memory. For example,
let's say your CPU loads memory, say, 4 bytes at a time from addresses
that are a multiple of four. Therefore, if you access 4 bytes from
memory address 4, the CPU will load memory addresses 4,5,6, and 7 all at
once in a single operation. However, if you access 4 bytes from memory
address 5, the CPU will take two operations: one to load from 4,5,6, and
7, and another to load from 8,9,10, and 11. It will then have to shift
the bytes around into their proper position. So, if your data is not
aligned on the same lines as your CPU's memory access, it can take quite
a bit longer for the CPU to grab data for you.

Slower access -- anywhere from three or four times slower
to a few thousand times slower -- is one possibility. Another
is that your program dies on a trap or signal of some kind.
Still another (which I actually encountered and recall with horror)
is that the access runs at full speed but ignores the "offending"
low-order address bits: You wind up fetching from or storing to
some memory "near" the intended object ...

As far as the C Standard is concerned, even these three
outcomes do not exhaust the possibilities: mis-aligned accesses
invoke Undefined Behavior, meaning that *all* bets are off.
 
M

Mac

but what KR mentioned that it is safer to cast a larger data type
pointer into a smaller one.
But the vice versa is dangerous.
e.g. char is the smallest data type available , so pointer to every
data type can be casted
to char*. please point me if I i am wrong.

and in above snippet why we need to add 1 in statement foo = 1 +
(unsigned char *)foo;
.


Regards,
Sachin

The point is that adding 1 in the code in question sets up the memory
misalignment. My example was an example of what NOT to do.

Different types are potentially made up of different numbers of bytes. We
can think that these types therefore have a starting address in memory.
The idea of alignment is that that starting addresses, for some types,
must be a multiple of some number greater than 1.

For example maybe some machines require the starting address for all ints
to be a multiple of 4, and for all doubles a multiple of 8. If you cast a
random char* to an int*, the resulting int* may not have correct alignment
for the type. That is, the address may not be evenly divisible by 4. This
violates the rule of that particular system, and will cause some kind of
fatal error.

At this stage you probably shouldn't worry about alignment.

--Mac
 
S

sachin_mzn

Hi Jonathan,

here I am confused by your staement 'if you access 4 bytes from memory
address 5, the CPU will take two operations' .

Can there be any practical situation where one can access 4 bytes
simultaneously
from address 5. My understanding is that we can get value only at that
particular address
otherwise we may get Bus Error on some platform.

I try to explain this by example
int i = 0x01020304;
int *p = &i;
p = 1+ (unsigned char*)p;
int j = *p; ----> /Oops this statement gives bus error;

But

*(1+ (unsigned char*)p) will print value at address at next byte of p.
that is 02 in Big endian machine.
Please tell me if i am wrong here

-Sachin
 
K

Keith Thompson

here I am confused by your staement 'if you access 4 bytes from memory
address 5, the CPU will take two operations' .

Can there be any practical situation where one can access 4 bytes
simultaneously from address 5. My understanding is that we can get
value only at that particular address otherwise we may get Bus Error
on some platform.

Sure. The behavior can vary from one platform to another. I think
most modern systems require strict alignment, generating a trap (such
as a bus error) on a misaligned operand. But I've seen systems that
can grab 4 bytes from an odd address (with or without a performance
penalty), and others that quietly ignore the low-order two bits of the
address.

All such cases are covered by "undefined behavior" in C.
 

Ask a Question

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.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top