Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #59518 > unrolled thread

Alignment requirement of basic types

Started byNoob <root@127.0.0.1>
First post2015-04-03 15:48 +0200
Last post2015-04-04 23:15 +0000
Articles 15 — 10 participants

Back to article view | Back to comp.lang.c


Contents

  Alignment requirement of basic types Noob <root@127.0.0.1> - 2015-04-03 15:48 +0200
    Re: Alignment requirement of basic types Tim Prince <tprince@computer.org> - 2015-04-03 10:23 -0400
    Re: Alignment requirement of basic types James Kuyper <jameskuyper@verizon.net> - 2015-04-03 11:37 -0400
      Re: Alignment requirement of basic types John Temples <usenet@xargs-spam.com> - 2015-04-03 17:21 +0000
        Re: Alignment requirement of basic types James Kuyper <jameskuyper@verizon.net> - 2015-04-03 13:45 -0400
          Re: Alignment requirement of basic types Kaz Kylheku <kaz@kylheku.com> - 2015-04-03 18:40 +0000
        Re: Alignment requirement of basic types Keith Thompson <kst-u@mib.org> - 2015-04-03 10:50 -0700
        Re: Alignment requirement of basic types glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-04-03 19:02 +0000
      Re: Alignment requirement of basic types Kaz Kylheku <kaz@kylheku.com> - 2015-04-03 18:01 +0000
    Re: Alignment requirement of basic types Richard Damon <Richard@Damon-Family.org> - 2015-04-03 12:05 -0400
      Re: Alignment requirement of basic types glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-04-03 16:48 +0000
    Re: Alignment requirement of basic types Kaz Kylheku <kaz@kylheku.com> - 2015-04-03 16:46 +0000
      Re: Alignment requirement of basic types Keith Thompson <kst-u@mib.org> - 2015-04-03 11:06 -0700
        Re: Alignment requirement of basic types Robert Wessel <robertwessel2@yahoo.com> - 2015-04-05 22:22 -0500
    Re: Alignment requirement of basic types Waldek Hebisch <hebisch@antispam.uni.wroc.pl> - 2015-04-04 23:15 +0000

#59518 — Alignment requirement of basic types

FromNoob <root@127.0.0.1>
Date2015-04-03 15:48 +0200
SubjectAlignment requirement of basic types
Message-ID<mfm5mg$4rp$1@dont-email.me>
Hello,

I had always been under the impression that objects of a given type
had to be size-aligned, i.e.
2-byte objects had to be 2-byte aligned,
4-byte objects had to be 4-byte aligned,
etc

However, I could not find this guarantee in C99 TC3 (N1256).
And another poster claims that platforms may allow 4-byte
objects to be {1,2,4}-byte aligned.

I suppose I was mistaken?

Do you know platforms where 4-byte types are only 2-byte aligned?

Perhaps 8086 had 32-bit longs that were only 16-bit aligned?

Maybe recent platforms have 64-bit long longs that are only
32-bit aligned?

Regards.

[toc] | [next] | [standalone]


#59520

FromTim Prince <tprince@computer.org>
Date2015-04-03 10:23 -0400
Message-ID<co7m3gF294fU1@mid.individual.net>
In reply to#59518
On 4/3/2015 9:48 AM, Noob wrote:

> I had always been under the impression that objects of a given type
> had to be size-aligned, i.e.
> 2-byte objects had to be 2-byte aligned,
> 4-byte objects had to be 4-byte aligned,
> etc
> 
> However, I could not find this guarantee in C99 TC3 (N1256).
> And another poster claims that platforms may allow 4-byte
> objects to be {1,2,4}-byte aligned.
> 
> I suppose I was mistaken?
> 
> Do you know platforms where 4-byte types are only 2-byte aligned?
> 
> Perhaps 8086 had 32-bit longs that were only 16-bit aligned?
> 
> Maybe recent platforms have 64-bit long longs that are only
> 32-bit aligned?

The "guarantee" for mis-aligned data e.g. in a struct is that padding
will vary among platforms.  On the most common platforms it can be a
trade-off between speed and compactness of data structures.
The x86 32-bit mode platforms have no inherent 64-bit alignment for
int64_t scalar data types, as they are implemented as 32-bit data pairs,
while the 64-bit mode on the same CPUs includes native 64-bit int64_t
with preferred alignment.  Yet both modes have alignment requirements
for vectorized int64_t.  In AVX mode the alignment requirement for
32-byte objects increases to 32-byte alignment.
As far as I know, the alignment requirements for objects bigger than 8
bytes or 64 bits are not in the C standard, but are part of OS ABI.
As you allude, there is support for odd byte alignment of scalar data
types on this hardware, at a penalty in performance.
So you can waste a lot of time and incur non-portability by exploiting
the ability of these platforms to support non-standard alignments.

[toc] | [prev] | [next] | [standalone]


#59524

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-04-03 11:37 -0400
Message-ID<551EB3B9.7090206@verizon.net>
In reply to#59518
On 04/03/2015 09:48 AM, Noob wrote:
> Hello,
> 
> I had always been under the impression that objects of a given type
> had to be size-aligned, i.e.
> 2-byte objects had to be 2-byte aligned,
> 4-byte objects had to be 4-byte aligned,
> etc
> 
> However, I could not find this guarantee in C99 TC3 (N1256).
> And another poster claims that platforms may allow 4-byte
> objects to be {1,2,4}-byte aligned.
> 
> I suppose I was mistaken?

Yes.

The only relevant requirement is that sizeof(type) must be a positive
integer multiple of _Alignof(type). This requirement is not explicitly
stated anywhere, but it can be derived from consideration of how arrays
are implemented. It's entirely possible to meet that requirement by
having _Alignof(type) be 1 for all types.

Note: _Alignof() is a new feature of C2011, while your question is about
C99. However, the concept of alignment existed even in C90, and
_Alignof() provides a convenient notation for talking about that
concept, even when discussing versions of C that don't support that feature.

C2011 requires that alignments must be powers of 2, no such requirement
existed in earlier versions of the C standard. I've no idea whether
there's ever been an implementation of C where that wasn't the case.

> Do you know platforms where 4-byte types are only 2-byte aligned?

I'm prohibited from writing platform-specific code. As a result, I've
specialized in knowing what's not guaranteed, and how to write code so
it doesn't rely on those non-existent guarantees. I'm correspondingly
less well informed about what actual implementations do. Other people
here who are allowed to write non-portable code can answer that question
better than I can.

[toc] | [prev] | [next] | [standalone]


#59530

FromJohn Temples <usenet@xargs-spam.com>
Date2015-04-03 17:21 +0000
Message-ID<slrnmhtj1m.gus.usenet@xargs-spam.com>
In reply to#59524
On 2015-04-03, James Kuyper <jameskuyper@verizon.net> wrote:
> C2011 requires that alignments must be powers of 2, no such requirement
> existed in earlier versions of the C standard. I've no idea whether
> there's ever been an implementation of C where that wasn't the case.

I have used 8-bit platforms with C compilers that supported 24-bit
integer and floating point types.  These platforms had no alignment
requirements for multi-byte objects, so it was possible to have
objects aligned on a three-byte boundary.

[toc] | [prev] | [next] | [standalone]


#59532

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-04-03 13:45 -0400
Message-ID<551ED1A1.8090009@verizon.net>
In reply to#59530
On 04/03/2015 01:21 PM, John Temples wrote:
> On 2015-04-03, James Kuyper <jameskuyper@verizon.net> wrote:
>> C2011 requires that alignments must be powers of 2, no such requirement
>> existed in earlier versions of the C standard. I've no idea whether
>> there's ever been an implementation of C where that wasn't the case.
> 
> I have used 8-bit platforms with C compilers that supported 24-bit
> integer and floating point types.  These platforms had no alignment
> requirements for multi-byte objects, so it was possible to have
> objects aligned on a three-byte boundary.

The C standard defines "alignment" as a "requirement that objects of a
particular type be located on storage boundaries with addresses that are
particular multiples of a byte address" (3.2p1). "No alignment
requirement" is slightly a misnomer - the correct way to say it is that
the  alignment requirement is 1, which is a power of 2.

Having "no alignment requirement" would correspond to allowing the start
of an object of that type to be anywhere, even an irrational fraction of
the way between the start of one byte and the start of the next byte. C
doesn't allow such things. An alignment requirement must be a positive
integer (since C90) and more specifically, "a non-negative integral
power of 2" (since C2011 - 6.2.8p4).

[toc] | [prev] | [next] | [standalone]


#59538

FromKaz Kylheku <kaz@kylheku.com>
Date2015-04-03 18:40 +0000
Message-ID<20150403112053.496@kylheku.com>
In reply to#59532
On 2015-04-03, James Kuyper <jameskuyper@verizon.net> wrote:
> On 04/03/2015 01:21 PM, John Temples wrote:
>> On 2015-04-03, James Kuyper <jameskuyper@verizon.net> wrote:
>>> C2011 requires that alignments must be powers of 2, no such requirement
>>> existed in earlier versions of the C standard. I've no idea whether
>>> there's ever been an implementation of C where that wasn't the case.
>> 
>> I have used 8-bit platforms with C compilers that supported 24-bit
>> integer and floating point types.  These platforms had no alignment
>> requirements for multi-byte objects, so it was possible to have
>> objects aligned on a three-byte boundary.
>
> The C standard defines "alignment" as a "requirement that objects of a
> particular type be located on storage boundaries with addresses that are
> particular multiples of a byte address" (3.2p1). "No alignment
> requirement" is slightly a misnomer - the correct way to say it is that
> the  alignment requirement is 1, which is a power of 2.

Another view is that an alignment requirement, if it exists, is that
a type be located on storage boundaries which are a product of
some subset of the integer factors of the size of the type (possibly
with a requirement that repeated factors be included as separate
members of the set).

1 is not a factor of any integer; factors start at 2. So if there is no
alignment requirement, the subset of integer factors whose product
is the alignment is empty.

If a number must be put on this situation, then it can be regarded
as an alignment of 1. This agrees with the very useful convention that
the product of an empty set of numbers is 1.

> Having "no alignment requirement" would correspond to allowing the start
> of an object of that type to be anywhere, even an irrational fraction of
> the way between the start of one byte and the start of the next byte. C
> doesn't allow such things. An alignment requirement must be a positive
> integer (since C90) and more specifically, "a non-negative integral
> power of 2" (since C2011 - 6.2.8p4).

An alignment requirement is a requirement which renders certain results of
pointer arithmetic incorrect.

Since no fractional address can be the result of pointer arithmetic,
considering such is moot. If no pointer arithmetic is incorrect on account
of the multiple of the address, then there is no alignment requirement
in effect.

Or, from a slightly different perspective, the smallest addressable unit of
storage is the byte in C. This requirement is independent of anything that
discusses alignment.

[toc] | [prev] | [next] | [standalone]


#59533

FromKeith Thompson <kst-u@mib.org>
Date2015-04-03 10:50 -0700
Message-ID<878ue9yucv.fsf@kst-u.example.com>
In reply to#59530
John Temples <usenet@xargs-spam.com> writes:
> On 2015-04-03, James Kuyper <jameskuyper@verizon.net> wrote:
>> C2011 requires that alignments must be powers of 2, no such requirement
>> existed in earlier versions of the C standard. I've no idea whether
>> there's ever been an implementation of C where that wasn't the case.
>
> I have used 8-bit platforms with C compilers that supported 24-bit
> integer and floating point types.  These platforms had no alignment
> requirements for multi-byte objects, so it was possible to have
> objects aligned on a three-byte boundary.

Sure, but the alignment of the type would be 1 byte, not 3.

A 32-bit int object on a system where int has a 4-byte alignment
requirement might *happen* to be aligned on, say, a 12-byte boundary,
but that's not meaningful.  The question on which James has no idea
(and neither do I) is whether any C implementation imposes a required
alignment that's not a power of 2.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#59539

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-04-03 19:02 +0000
Message-ID<mfmo4u$jsm$1@speranza.aioe.org>
In reply to#59530
John Temples <usenet@xargs-spam.com> wrote:
> On 2015-04-03, James Kuyper <jameskuyper@verizon.net> wrote:
>> C2011 requires that alignments must be powers of 2, no such requirement
>> existed in earlier versions of the C standard. I've no idea whether
>> there's ever been an implementation of C where that wasn't the case.
 
> I have used 8-bit platforms with C compilers that supported 24-bit
> integer and floating point types.  These platforms had no alignment
> requirements for multi-byte objects, so it was possible to have
> objects aligned on a three-byte boundary.

It would be interesting to have a machine with 24 bit int that
required 3 byte (multiple of three) alignment. I suppose it isn't
so hard to build a 24 bit wide memory with byte addressing.

I have wondered about cache systems using other than power of two
interleave. 

Fortran allows for any integer base greater than 1, so one could
have a trinary computer with trinary addressing, and multiple of
three alignment.

There have been decimal computers with decimal addressing, but 
I believe with no alignment requirement.

-- glen

[toc] | [prev] | [next] | [standalone]


#59534

FromKaz Kylheku <kaz@kylheku.com>
Date2015-04-03 18:01 +0000
Message-ID<20150403102444.291@kylheku.com>
In reply to#59524
On 2015-04-03, James Kuyper <jameskuyper@verizon.net> wrote:
> C2011 requires that alignments must be powers of 2, no such requirement
> existed in earlier versions of the C standard.

What problem does that solve?

The implementor and user of a compiler that has 6 byte types with
3 byte alignment are now in nonconforming land.

Business as usual, otherwise.

[toc] | [prev] | [next] | [standalone]


#59525

FromRichard Damon <Richard@Damon-Family.org>
Date2015-04-03 12:05 -0400
Message-ID<NSyTw.156257$uD5.43837@fx02.iad>
In reply to#59518
On 4/3/15 9:48 AM, Noob wrote:
> Hello,
>
> I had always been under the impression that objects of a given type
> had to be size-aligned, i.e.
> 2-byte objects had to be 2-byte aligned,
> 4-byte objects had to be 4-byte aligned,
> etc
>
> However, I could not find this guarantee in C99 TC3 (N1256).
> And another poster claims that platforms may allow 4-byte
> objects to be {1,2,4}-byte aligned.
>

As has been mentioned, the required (or implemented) alignment for a 
type can be any value between 1 and sizeof the type, as long as it 
divides into sizeof the type (this comes out of the definition of how 
arrays work).

> I suppose I was mistaken?

Yes. In fact there were machines that could byte align almost all 
objects, at a cost to access.
>
> Do you know platforms where 4-byte types are only 2-byte aligned?
>

It is common that alignment requirements are not stricter than the 
machines memory bus width, so a machine that fetches only 16 bits at a 
time, often will not have alignment restrictions stricter than that for 
many types. (there may be special objects with stricter alignment, like 
paging tables).

> Perhaps 8086 had 32-bit longs that were only 16-bit aligned?
>

I seem to remember that as true.

> Maybe recent platforms have 64-bit long longs that are only
> 32-bit aligned?
>
> Regards.

[toc] | [prev] | [next] | [standalone]


#59528

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-04-03 16:48 +0000
Message-ID<mfmg9g$nd$1@speranza.aioe.org>
In reply to#59525
Richard Damon <Richard@damon-family.org> wrote:
> On 4/3/15 9:48 AM, Noob wrote:
(snip)
>> Do you know platforms where 4-byte types are only 2-byte aligned?

> It is common that alignment requirements are not stricter than the 
> machines memory bus width, so a machine that fetches only 16 bits at a 
> time, often will not have alignment restrictions stricter than that for 
> many types. (there may be special objects with stricter alignment, like 
> paging tables).
 
>> Perhaps 8086 had 32-bit longs that were only 16-bit aligned?
 
> I seem to remember that as true.

The history is more interesting for floating point types.

The original 8087 and the 80287 have a 16 bit data bus, and only
needed 16 bit (2 byte) alignment for 32 bit and 64 bit floating
point (C float and double).   

(Needed instead of required. They can work without such alignment,
but run much slower.)

Later, when processors with 32 bit and 64 bit data buses came along,
many compilers still generated, and C malloc() still returned,
addresses with only two byte alignment. While it worked, it was
much slower than it should have been with such misaligned data.
 
>> Maybe recent platforms have 64-bit long longs that are only
>> 32-bit aligned?

-- glen

[toc] | [prev] | [next] | [standalone]


#59527

FromKaz Kylheku <kaz@kylheku.com>
Date2015-04-03 16:46 +0000
Message-ID<20150403092630.239@kylheku.com>
In reply to#59518
On 2015-04-03, Noob <root@127.0.0.1> wrote:
> Hello,
>
> I had always been under the impression that objects of a given type
> had to be size-aligned, i.e.
> 2-byte objects had to be 2-byte aligned,
> 4-byte objects had to be 4-byte aligned,
> etc
>
> However, I could not find this guarantee in C99 TC3 (N1256).
> And another poster claims that platforms may allow 4-byte
> objects to be {1,2,4}-byte aligned.

The C standards allows implementations to impose alignment
requirements on pointers to types that are more than one
byte wide.

> I suppose I was mistaken?
>
> Do you know platforms where 4-byte types are only 2-byte aligned?

On x86, four byte types do not have an alignment *requirement*.
This means that you can do this:

   char *mem = malloc(5);
   int *p = (int *) mem + 1;
   *p = 42;

since the alignment requirement is not imposed, you have more
freedom in how you treat this memory. Of course, the code is not
portable: strictly portable ISO C code has to assume that the
alignment of int is the strictest it can be: sizeof (int).

Now in spite of there not being an alignment requirement from the hardware, x86
compilers do align four byte integers, when they control their allocation: e.g.
as static or local variables, or struct members.

This is not required; it is for reasons of performance or
layout compatibility.

ISO C does not dictate all the details about how declared objects,
and structure members should be laid out.

There are some rules. A struct must include any necessary padding so that all
its members are properly aligned with regard to their alignment requirements,
when that struct is aggregated into an array. That padding must be at the
end of the structure. Members are laid out in a stucture at increasing
addreseses in the order in which their declarations appear.

> Perhaps 8086 had 32-bit longs that were only 16-bit aligned?

The 8086 and 8088 processors do not have alignment restrictions; you can read
words from odd addresses. Many classic CISC processors are that way, such
as Motorola 68K.

Some processors with a RISC-y lineage enforce alignment, but have provisions
for trap handlers in the operating system kernel to emulate misaligned
accesses (very expensively). So this code will work:

   char *mem = malloc(5);
   int *p = (int *) mem + 1;
   *p = 42;

but the *p = 42 will trigger a trap that could cost hundreds of machine
cycles to execute.

On a processor which supports misaligned accesses in hardware, thre
could still be a performance penalty, though it won't be hundreds
of cycles. More bus cycles may be needed for the hardware to access
two adjacent aligned words.

Some RISC-like instruction sets also have special instructions for "skewed"
memory accesses, which read or write a word-sized quantity at an aligned
address, but also shift it at the same time. With a suitable pair of these
instructions, you can read a 32 bit value (or whatever) at an address that is 1
mod 4 (or whatever).

[toc] | [prev] | [next] | [standalone]


#59535

FromKeith Thompson <kst-u@mib.org>
Date2015-04-03 11:06 -0700
Message-ID<874moxytl5.fsf@kst-u.example.com>
In reply to#59527
Kaz Kylheku <kaz@kylheku.com> writes:
[...]
> The 8086 and 8088 processors do not have alignment restrictions; you can read
> words from odd addresses. Many classic CISC processors are that way, such
> as Motorola 68K.
[...]

My admittedly hazy memory tells me that accessing a 16-bit word at an
odd address on a 68K would cause a fatal trap, probably a bus error.

(At least one non-C implementation took advantage of this by making the
null pointer's representation 0x1, so any attempt to dereference it
would cause a trap.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#59673

FromRobert Wessel <robertwessel2@yahoo.com>
Date2015-04-05 22:22 -0500
Message-ID<vsu3iala45dfipdoigg4omgf8iu8uoq93n@4ax.com>
In reply to#59535
On Fri, 03 Apr 2015 11:06:46 -0700, Keith Thompson <kst-u@mib.org>
wrote:

>Kaz Kylheku <kaz@kylheku.com> writes:
>[...]
>> The 8086 and 8088 processors do not have alignment restrictions; you can read
>> words from odd addresses. Many classic CISC processors are that way, such
>> as Motorola 68K.
>[...]
>
>My admittedly hazy memory tells me that accessing a 16-bit word at an
>odd address on a 68K would cause a fatal trap, probably a bus error.


That was the case on the 68000 and 68010, but on the '020 most of the
alignment requirements were eliminated.

[toc] | [prev] | [next] | [standalone]


#59602

FromWaldek Hebisch <hebisch@antispam.uni.wroc.pl>
Date2015-04-04 23:15 +0000
Message-ID<mfprb3$8lb$2@z-news2.pwr.wroc.pl>
In reply to#59518
Noob <root@127.0.0.1> wrote:
> Hello,
> 
> I had always been under the impression that objects of a given type
> had to be size-aligned, i.e.
> 2-byte objects had to be 2-byte aligned,
> 4-byte objects had to be 4-byte aligned,
> etc
> 
> However, I could not find this guarantee in C99 TC3 (N1256).
> And another poster claims that platforms may allow 4-byte
> objects to be {1,2,4}-byte aligned.
> 
> I suppose I was mistaken?
> 
> Do you know platforms where 4-byte types are only 2-byte aligned?

gcc for MSP430 user 2-byte aligment.  In general, 16-bit processors
usualy use 2-byte aligment.  16-bitter are relatively rare,
but probably more in units than 64-bit processors.  Note
that most processors in use are 8-bitters that use 1-byte
aligment (they are buried in various devices, your PC is likely
to contain a few inside).
 

-- 
                              Waldek Hebisch
hebisch@antispam.uni.wroc.pl  For mail replace antispam by math

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web