By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,563 Members | 1,066 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,563 IT Pros & Developers. It's quick & easy.

struct and union alignment

P: n/a

I would like to check if I understand the following excerpt correctly:

6.2.5#26 (Types):
All pointers to structure types shall have the same representation and
alignment requirements as each other. All pointers to union types shall
have the same representation and alignment requirements as each other.

Does it mean that *all* structure (or union) types have the same
alignment?
Eg. type
struct { char c; }
and
struct { long double ldt[11]; }
have the same alignment requirements?
If the answer to the above is "yes", then it means that:

1. Alignment of any struct (union) must be maximum or its multiple.
(Alignment of a struct (union) can't be less restrictive than that
of its members[*]. Since any (object) type may be a member, at
least one struct (union) must have at least that type's alignment.
Since all struct (union) types have the same alignment,
it follows that all must meet the the maximum one.)

2. Alignment requirements for all structs _and_ unions are the same.
(Since you can have a struct as a member of a union, and a union as a
member of a struct, it follows that their alignments must be the same).
[*] During google search I have learned that a type's alignments
may differ in a struct and outside. Here I rather mean the least
restrictive alignment requirement for a type that has to be met
for a particular architecture.
--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #1
Share this Question
Share on Google+
67 Replies


P: n/a
"S.Tobias" <sN*******@amu.edu.pl> writes:
I would like to check if I understand the following excerpt correctly:

6.2.5#26 (Types):
All pointers to structure types shall have the same representation and
alignment requirements as each other. All pointers to union types shall
have the same representation and alignment requirements as each other.

Does it mean that *all* structure (or union) types have the same
alignment?
Eg. type
struct { char c; }
and
struct { long double ldt[11]; }
have the same alignment requirements?


No, it's referring to the alignment of the pointer, not the alignment
of the struct or union.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #2

P: n/a
On 23 Sep 2004 19:10:38 GMT
"S.Tobias" <sN*******@amu.edu.pl> wrote:

I would like to check if I understand the following excerpt correctly:

6.2.5#26 (Types):
All pointers to structure types shall have the same representation
and alignment requirements as each other. All pointers to union
types shall have the same representation and alignment requirements
as each other.

Does it mean that *all* structure (or union) types have the same
alignment?
Eg. type
struct { char c; }
and
struct { long double ldt[11]; }
have the same alignment requirements?
Yes. Think about what what has to be done to implement pointers to
anonymous structs. When the compiler is compiling a piece of code that
increments a pointer to an anonymous struct all it knows is that it is a
pointer to a struct, so how else could this have been done?
If the answer to the above is "yes", then it means that:

1. Alignment of any struct (union) must be maximum or its multiple.
(Alignment of a struct (union) can't be less restrictive than that
of its members[*]. Since any (object) type may be a member, at
least one struct (union) must have at least that type's alignment.
Since all struct (union) types have the same alignment,
it follows that all must meet the the maximum one.)
Yes.
2. Alignment requirements for all structs _and_ unions are the same.
(Since you can have a struct as a member of a union, and a union as
a member of a struct, it follows that their alignments must be the
same).
Sounds logical to me.
[*] During google search I have learned that a type's alignments
may differ in a struct and outside. Here I rather mean the least
restrictive alignment requirement for a type that has to be met
for a particular architecture.


The alignment inside a struct is at least as strict as outside, since
you can take a pointer to an element in a struct. However, yes, I
can't think of anything that would prevent the compiler from padding
things out further.
--
Flash Gordon
Sometimes I think shooting would be far too good for some people.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #3

P: n/a
Keith Thompson <ks***@mib.org> wrote:
"S.Tobias" <sN*******@amu.edu.pl> writes:
6.2.5#26 (Types):
All pointers to structure types shall have the same representation and
alignment requirements as each other. All pointers to union types shall
have the same representation and alignment requirements as each other.

Does it mean that *all* structure (or union) types have the same
alignment?
No, it's referring to the alignment of the pointer, not the alignment
of the struct or union.
What's the difference?

Strictly speaking, (complete) _types_ have alignment requirements.
As I understand it, when we say "a pointer to TYPE has alignment
requirements", we mean exactly same thing as: "TYPE has alignment
requirements"; I don't see any reason to differentiate between these two.

(I have also considered "pointer to struct" type (ie.: struct s *)
alignment requirements, but this doesn't make sense in context of
the quoted part of the Standard.)
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #4

P: n/a
Flash Gordon <sp**@flash-gordon.me.uk> writes:
On 23 Sep 2004 19:10:38 GMT
"S.Tobias" <sN*******@amu.edu.pl> wrote:
I would like to check if I understand the following excerpt correctly:

6.2.5#26 (Types):
All pointers to structure types shall have the same representation
and alignment requirements as each other. All pointers to union
types shall have the same representation and alignment requirements
as each other.

Does it mean that *all* structure (or union) types have the same
alignment?
Eg. type
struct { char c; }
and
struct { long double ldt[11]; }
have the same alignment requirements?


Yes. Think about what what has to be done to implement pointers to
anonymous structs. When the compiler is compiling a piece of code that
increments a pointer to an anonymous struct all it knows is that it is a
pointer to a struct, so how else could this have been done?


When 6.2.5 discusses the alignment requirements of various types, it's
clear that it's referring to the alignment of objects of the type
itself. It uses similar wording in 6.2.5p26, so I think it's
referring to the alignment of a pointer object, not the alignment of
what it points to.

I don't think this is a problem for pointers to anonymous structs.
You can't create a pointer value that points to an anonymous struct
without knowing what the actual type is. Similarly, you can't
increment a pointer to an anonymous struct without knowing the
struct's size.

I believe that an implementation in which pointer values are simple
byte addresses, small structs (struct { char c; }) have, say, 1-byte
alignment, and larger structs have, say, 4-byte alignment could be
conforming. Can you think of a concrete example where this would
cause problems?

[...]
[*] During google search I have learned that a type's alignments
may differ in a struct and outside. Here I rather mean the least
restrictive alignment requirement for a type that has to be met
for a particular architecture.


The alignment inside a struct is at least as strict as outside, since
you can take a pointer to an element in a struct. However, yes, I
can't think of anything that would prevent the compiler from padding
things out further.


Assume in the following that sizeof(int) == 4.

On some hardware, an int can be accessed more efficiently if it's
aligned on a 4-byte boundary, but can still be accessed if it's merely
byte-aligned. An implementation could consistently choose to align
all declared int objects on 4-byte boundary, but use byte alignment
for struct members that are of type int (to save space). Or vice
versa.

I'm not saying that this would be a sensible thing to do, but it's
legal.

I suppose we're talking about two different meanings of "alignment
requirements": the alignment the compiler chooses to use for a given
type, and the alignment that's actually required by the hardware. The
former needs to be at least as strict as the latter, but it needn't be
the same.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #5

P: n/a
Flash Gordon <sp**@flash-gordon.me.uk> wrote:
On 23 Sep 2004 19:10:38 GMT
"S.Tobias" <sN*******@amu.edu.pl> wrote:
Does it mean that *all* structure (or union) types have the same
alignment? Yes. Think about what what has to be done to implement pointers to
anonymous structs. When the compiler is compiling a piece of code that
increments a pointer to an anonymous struct all it knows is that it is a
pointer to a struct, so how else could this have been done?
I'm sorry, but I can't see how can you define a pointer to anonymous
struct in the first place (since that struct has no name). And how
that could relate to alignment issues (incrementing a pointer has
at most to do with type size, not alignment).

[ C Std doesn't define anonymous structs. I've found somewhere the
anonymous structs are structs "declared" within other structs/unions,
that don't have a tag, object nor typedef name. ]

[*] During google search I have learned that a type's alignments
may differ in a struct and outside.

The alignment inside a struct is at least as strict as outside, since
you can take a pointer to an element in a struct. However, yes, I
can't think of anything that would prevent the compiler from padding
things out further.


I read someone saying that alignment requirements inside a struct might
be even less restrictive than outside (I've lost that post, but when I
find it I'll post it here). The explanation was like this: for example
a 32-bit int may have 2-byte alignment requirement, but if it's on 4-byte
boundary it's accessed faster. So an implementation might have 4-byte
int alignment outside structs, but for better packing reasons 2-byte
alignment inside.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #6

P: n/a
"S.Tobias" <sN*******@amu.edu.pl> writes:
Keith Thompson <ks***@mib.org> wrote:
"S.Tobias" <sN*******@amu.edu.pl> writes:
> 6.2.5#26 (Types):
> All pointers to structure types shall have the same representation and
> alignment requirements as each other. All pointers to union types shall
> have the same representation and alignment requirements as each other.
>
> Does it mean that *all* structure (or union) types have the same
> alignment?

No, it's referring to the alignment of the pointer, not the alignment
of the struct or union.


What's the difference?

Strictly speaking, (complete) _types_ have alignment requirements.
As I understand it, when we say "a pointer to TYPE has alignment
requirements", we mean exactly same thing as: "TYPE has alignment
requirements"; I don't see any reason to differentiate between these two.


It's just like the difference between the size of a pointer and the
size of what it points to.

For example, a pointer object might require 4-byte alignment, whereas
a char object requires only 1-byte alignment. When the standard says
void* and char* have to have the same alignment requirements, the
intent is that they're interchangeable as arguments to functions.
Requiring 1-byte alignment for char* but only 4-byte alignment for
void* could break this.

Look at the other references to alignment requirements in 6.2.5; they
clearly refer to the alignment of the type itself. 6.2.5#26 uses
similar wording, so it refers to the alignment of the pointers
themselves. (Alignment requirements for character types are discussed
elsewhere.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #7

P: n/a
"Flash Gordon" <sp**@flash-gordon.me.uk> wrote in message
news:ps************@brenda.flash-gordon.me.uk...
On 23 Sep 2004 19:10:38 GMT
"S.Tobias" <sN*******@amu.edu.pl> wrote:
Does it mean that *all* structure (or union) types have the same
alignment?
Eg. type
struct { char c; }
and
struct { long double ldt[11]; }
have the same alignment requirements?


Unions also have the caveat that they be aligned according to the most
restrictive item in the union. So a struct {char a; double z;} could
have a different alignment than union {char a; double z;}.

--
Mabden
Nov 14 '05 #8

P: n/a
On 23 Sep 2004 23:51:44 GMT, "S.Tobias" <sN*******@amu.edu.pl> wrote:
Keith Thompson <ks***@mib.org> wrote:
"S.Tobias" <sN*******@amu.edu.pl> writes:
> 6.2.5#26 (Types):
> All pointers to structure types shall have the same representation and
> alignment requirements as each other. All pointers to union types shall
> have the same representation and alignment requirements as each other.
>
> Does it mean that *all* structure (or union) types have the same
> alignment?
No, it's referring to the alignment of the pointer, not the alignment
of the struct or union.


What's the difference?

Strictly speaking, (complete) _types_ have alignment requirements.
As I understand it, when we say "a pointer to TYPE has alignment
requirements", we mean exactly same thing as: "TYPE has alignment
requirements"; I don't see any reason to differentiate between these two.


Actually, this is informally speaking, not strictly speaking.
Informally, some talk about aligning a pointer when we really mean
aligning the *VALUE* assigned to the pointer which is equivalent to
aligning the object the pointer points to.

Strictly speaking, when we talk about aligning a pointer we mean
aligning the pointer itself.

For example, on my system all pointers require four-byte alignment
while doubles require eight-byte alignment. A pointer to double need
only be aligned on a four-byte boundary but its value better be
aligned on an eight-byte boundary.

(I have also considered "pointer to struct" type (ie.: struct s *)
alignment requirements, but this doesn't make sense in context of
the quoted part of the Standard.)


Actually it does. If we have a number of different structs, some with
one-byte alignment, some with two, some with four, and some with
eight, a set of pointers to these different structs all have the same
alignment (four-byte on my system) and representation, even though the
objects they point to (and therefore the values they contain) have
different requirements.

Just as note, this is what allows a struct type to contain a member
which is a pointer to the same struct type (think linked list). At
the time the member is being processed by the compiler, the alignment
requirements of the struct are not yet known (the struct is still
incomplete) but the alignment requirements of the pointer are known so
the compiler can decide how much padding is needed.
<<Remove the del for email>>
Nov 14 '05 #9

P: n/a
On 23 Sep 2004 19:10:38 GMT, "S.Tobias" <sN*******@amu.edu.pl> wrote:

I would like to check if I understand the following excerpt correctly:

6.2.5#26 (Types):
All pointers to structure types shall have the same representation and
alignment requirements as each other. All pointers to union types shall
have the same representation and alignment requirements as each other.

Does it mean that *all* structure (or union) types have the same
alignment?
Eg. type
struct { char c; }
and
struct { long double ldt[11]; }
have the same alignment requirements?
No. It is only talking about the pointers themselves and not about
the values assigned to the pointers or the objects the pointers point
to.


If the answer to the above is "yes", then it means that:

1. Alignment of any struct (union) must be maximum or its multiple.
(Alignment of a struct (union) can't be less restrictive than that
of its members[*]. Since any (object) type may be a member, at
least one struct (union) must have at least that type's alignment.
Since all struct (union) types have the same alignment,
it follows that all must meet the the maximum one.)
Since the answer is no, the conclusion is unwarranted.

2. Alignment requirements for all structs _and_ unions are the same.
(Since you can have a struct as a member of a union, and a union as a
member of a struct, it follows that their alignments must be the same).
Ditto.

[*] During google search I have learned that a type's alignments
may differ in a struct and outside. Here I rather mean the least
restrictive alignment requirement for a type that has to be met
for a particular architecture.


I don't think so in standard C. It may be possible with some compiler
specific extensions (e.g., some have an option to eliminate padding).
<<Remove the del for email>>
Nov 14 '05 #10

P: n/a
"Mabden" <mabden@sbc_global.net> writes:
"Flash Gordon" <sp**@flash-gordon.me.uk> wrote in message
news:ps************@brenda.flash-gordon.me.uk...
On 23 Sep 2004 19:10:38 GMT
"S.Tobias" <sN*******@amu.edu.pl> wrote:
> Does it mean that *all* structure (or union) types have the same
> alignment?
> Eg. type
> struct { char c; }
> and
> struct { long double ldt[11]; }
> have the same alignment requirements?


Unions also have the caveat that they be aligned according to the most
restrictive item in the union. So a struct {char a; double z;} could
have a different alignment than union {char a; double z;}.


Both unions and structs have to be aligned at least as strictly as
their most strictly aligned member. Both struct {char a; double z;}
and union {char a; double z;} have to be aligned in a way that allows
the 'z' member to be accessed. (This can require padding between
members, and possibly after the last member, for a struct; any padding
in a union occurs after each member, since all members have the same
offset.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #11

P: n/a
S.Tobias wrote:
I'm sorry, but I can't see how can you define a pointer to anonymous
struct in the first place (since that struct has no name).


struct {
int a;
int b;
} *pointer_to_anonymous_struct;
Christian
Nov 14 '05 #12

P: n/a
Keith Thompson <ks***@mib.org> wrote:
For example, a pointer object might require 4-byte alignment, whereas
a char object requires only 1-byte alignment. When the standard says
void* and char* have to have the same alignment requirements, the
intent is that they're interchangeable as arguments to functions.
Right.
extern char *pc;
void free(void *p);
free(pc); //correct

(Note: we don't need same representation requirement in the above
example. This requirement is necessary eg. for variadic arguments:
printf("%p", pc);
- no cast to void* required.)
Requiring 1-byte alignment for char* but only 4-byte alignment for
void* could break this.
No. I see no reason to require same alignment for types void* and char*,
because in function arguments they're passed by *value* (think conversion).
Similarly, long and char do not have to have same alignment, but we may
always use them in arguments "interchangeably":
extern long l;
extern char c;
int f_char(unsigned char c);
int f_long(unsigned long l);
f_char(l); //both calls correct
f_long(c);

Look at the other references to alignment requirements in 6.2.5; they
clearly refer to the alignment of the type itself. 6.2.5#26 uses
similar wording, so it refers to the alignment of the pointers
themselves. (Alignment requirements for character types are discussed
elsewhere.)
I have looked in the entire text. The Standard uses the word "alignment"
in three ways: type (or object) alignment; pointer value alignment
(it uses words: "value", "result", "address"); or pointer alignment
(the way we discuss now).

The last manner is also found in: 6.3.2.3#7 (Pointers) and 7.20.3#1
(Memory management functions). See for yourself: in both cases "pointer
alignment" refers to the pointer *value*, not pointer type.
Barry Schwarz <sc******@deloz.net> wrote: On 23 Sep 2004 23:51:44 GMT, "S.Tobias" <sN*******@amu.edu.pl> wrote:
Strictly speaking, (complete) _types_ have alignment requirements.
As I understand it, when we say "a pointer to TYPE has alignment
requirements", we mean exactly same thing as: "TYPE has alignment
requirements"; I don't see any reason to differentiate between these two. Actually, this is informally speaking, not strictly speaking.
Informally, some talk about aligning a pointer when we really mean
aligning the *VALUE* assigned to the pointer which is equivalent to
aligning the object the pointer points to. Strictly speaking, when we talk about aligning a pointer we mean
aligning the pointer itself. (I have also considered "pointer to struct" type (ie.: struct s *)
alignment requirements, but this doesn't make sense in context of
the quoted part of the Standard.)


So this is actually what you and Keith think the Standard refers to!
So the fight is over "strictly" and "informally". I think that
the Standard in all cases means "informally".

Just as note, this is what allows a struct type to contain a member
which is a pointer to the same struct type (think linked list). At
the time the member is being processed by the compiler, the alignment
requirements of the struct are not yet known (the struct is still
incomplete) but the alignment requirements of the pointer are known so
the compiler can decide how much padding is needed.


While this might be a problem, I agree, this is an internal matter
of the implementation how it solves this (pointer type alignment and
padding before it). The Standard is a contract between an implementor
and a programmer. There is nothing a programmer can gain from
knowing that all pointer-to-struct types have same alignment and
thanks to it the compiler can easily construct a structure type.
I just think your argument misses the point.

OT:
The compiler might construct a struct type in several passes, each
time adjusting the padding before the pointer member.
This process must end, because there exists a maximum alignment.
========

My arguments:
6.2.5#26 (extended quote, to get more context)
A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.39) Similarly,
pointers to qualified or unqualified versions of compatible types
shall have the same representation and alignment requirements. All
pointers to structure types shall have the same representation and
alignment requirements as each other. All pointers to union types
shall have the same representation and alignment requirements
as each other. Pointers to other types need not have the same
representation or alignment requirements.

39) The same representation and alignment requirements are meant
to imply interchangeability as arguments to functions, return
values from functions, and members of unions.

Rationale:
[...] A pointer to void must have the same representation
and alignment as a pointer to char; the intent of this rule is
to allow existing programs that call library functions such as
memcpy and free to continue to work.

Remark: It is obvious the Standard means "pointers to (structure types)",
not "(pointers to structure) types". This follows from English grammar
rules, but please don't ask me for chapter and verse! :-)

The first part the Std talks about the "compatibility" of void* and char*
types. Here it definitely refers to alignment of pointer *values*.
This is required for conversions between void* and char* to be well
defined. Of course, the Std cannot say directly about requirements
for the types they point to, because void is not a complete type (but
this is the intention if we forget it for a while and treat void as an
integer type with size one, but not compatible with char).
(OTOH the Std could formally define alignment of void type to be equal
to that of char type.)

The Standard cannot refer to the alignment of _types_ void* and char*.
If it did, it would only concern conversions between void** and char**.
The only standard functions with that type are strto?() family and friends
(and then we should add same requirement for wchar_t* to be consistent).
The rationale mentions only functions like free() or memcpy(), ie. ones
that probably historically had int free(char*) prototypes before the
type void was introduced. Here, the alignment compatibility between
the _values_ of type void* and char* is essential - IOW it means the
resolution of void* and char* pointer types is the highest and both
are equivalent in this matter.

Then, after the word "Similarly", the Standard talks about alignment
of pointers to compatible types, struct and unions, and other types in
the same manner. There is no reason to believe it uses similar wording
in a different manner this time.

There is no advantage in guaranteeing same alignment for "pointers
to incompatible types" types (at least I can't think of any).
All of them can be stored as void* if need be.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #13

P: n/a
Christian Kandeler <ch****************@hob.de_invalid> wrote:
S.Tobias wrote:
I'm sorry, but I can't see how can you define a pointer to anonymous
struct in the first place (since that struct has no name).

struct {
int a;
int b;
} *pointer_to_anonymous_struct;


OIC, didn't think of that.

But then again, what would be a use for that? Since
this is not a struct object definition, there are no objects
of type pointer_to_anonymous_struct points to.

Mmmm, could it be:
pointer_to_anonymous_struct = malloc(sizeof *pointer_to_anonymous_struct);
?
But what is the point in having an anonymous struct then?

Could you supply a real-life example?

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #14

P: n/a
"S.Tobias" <sN*******@amu.edu.pl> wrote:
Christian Kandeler <ch****************@hob.de_invalid> wrote:
S.Tobias wrote:

I'm sorry, but I can't see how can you define a pointer to anonymous
struct in the first place (since that struct has no name).

struct {
int a;
int b;
} *pointer_to_anonymous_struct;


OIC, didn't think of that.

But then again, what would be a use for that? Since
this is not a struct object definition, there are no objects
of type pointer_to_anonymous_struct points to.

Mmmm, could it be:
pointer_to_anonymous_struct = malloc(sizeof *pointer_to_anonymous_struct);
?
But what is the point in having an anonymous struct then?

Could you supply a real-life example?


Maybe something like:

int main() {
uint32 x = 0x5678abcd;
struct {
uint16 hiword;
uint16 loword;
} *wordsinlong = &x;
printf("Hiword: %x\nLoword: %x",
words_in_long->hiword,
words_in_long->loword);
return 0;
}

--
Simon Stienen <http://dangerouscat.net> <http://slashlife.de>
»What you do in this world is a matter of no consequence,
The question is, what can you make people believe that you have done.«
-- Sherlock Holmes in "A Study in Scarlet" by Sir Arthur Conan Doyle
Nov 14 '05 #15

P: n/a
In <2r*************@uni-berlin.de> "S.Tobias" <sN*******@amu.edu.pl> writes:
Keith Thompson <ks***@mib.org> wrote:
"S.Tobias" <sN*******@amu.edu.pl> writes:
> 6.2.5#26 (Types):
> All pointers to structure types shall have the same representation and
> alignment requirements as each other. All pointers to union types shall
> have the same representation and alignment requirements as each other.
>
> Does it mean that *all* structure (or union) types have the same
> alignment?

No, it's referring to the alignment of the pointer, not the alignment
of the struct or union.


What's the difference?


If you can't grasp the difference between a pointer and the pointed-to
object, stop messing with the C standard and read K&R2 (again).

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Currently looking for a job in the European Union
Nov 14 '05 #16

P: n/a
"Mabden" <mabden@sbc_global.net> wrote in message
news:mB***************@newssvr14.news.prodigy.com. ..
"Flash Gordon" <sp**@flash-gordon.me.uk> wrote in message
news:ps************@brenda.flash-gordon.me.uk...
On 23 Sep 2004 19:10:38 GMT
"S.Tobias" <sN*******@amu.edu.pl> wrote:
Does it mean that *all* structure (or union) types have the same
alignment?
Eg. type
struct { char c; }
and
struct { long double ldt[11]; }
have the same alignment requirements?


Unions also have the caveat that they be aligned according to the most
restrictive item in the union. So a struct {char a; double z;} could
have a different alignment than union {char a; double z;}.


Wrong. Both the struct and union have the same
alignment as double. A struct's alignment is
the same as the strictest (widest) alignment
of any of its members, including nested aggregates.
Same rules apply for union. The alignment is that
of the strictest alignment of any of its members,
including nested aggregates (other unions or
structs).

Maybe you are confusing the size with alignment?
Nov 14 '05 #17

P: n/a
In <2r*************@uni-berlin.de> "S.Tobias" <sN*******@amu.edu.pl> writes:
Christian Kandeler <ch****************@hob.de_invalid> wrote:
S.Tobias wrote:
> I'm sorry, but I can't see how can you define a pointer to anonymous
> struct in the first place (since that struct has no name).

struct {
int a;
int b;
} *pointer_to_anonymous_struct;


OIC, didn't think of that.

But then again, what would be a use for that? Since
this is not a struct object definition, there are no objects
of type pointer_to_anonymous_struct points to.

Mmmm, could it be:
pointer_to_anonymous_struct = malloc(sizeof *pointer_to_anonymous_struct);
?
But what is the point in having an anonymous struct then?


Look at it the other way round: in your own example, what would be the
point of using a tag in the structure definition?
Could you supply a real-life example?


Sure:

struct { ... } foo, bar, baz;

foo, bar and baz are all the objects of this type needed by the program
and they are used in a single translation unit. What would a tag buy you?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Currently looking for a job in the European Union
Nov 14 '05 #18

P: n/a
Dan Pop <Da*****@cern.ch> wrote:
In <2r*************@uni-berlin.de> "S.Tobias" <sN*******@amu.edu.pl> writes:
Keith Thompson <ks***@mib.org> wrote:
No, it's referring to the alignment of the pointer, not the alignment
of the struct or union.
What's the difference?

If you can't grasp the difference between a pointer and the pointed-to
object, stop messing with the C standard and read K&R2 (again).


Why being so aggressive at me? My seemingly naive question was not
asked without a reason, which I explained at length in my answer
to Barry Schwarz' post (I assume that hadn't reached you before
you sent yours). I think my remark in parentheses (which you didn't
quote) more than suggests I do understand the difference between
pointer type and pointed to type (I explicitly wrote that I did consider
pointer type alignment possibility, but rejected it).

I don't understand how you can judge other people's understanding
only after one posting. Please, explain yourself.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #19

P: n/a
In article <news:2r*************@uni-berlin.de>
S.Tobias <sN*******@amu.edu.pl> wrote:
[much snippage]
The last manner is also found in: 6.3.2.3#7 (Pointers) and 7.20.3#1
(Memory management functions). See for yourself: in both cases "pointer
alignment" refers to the pointer *value*, not pointer type.


I am not going to address most of this (due to lack of time), but
I want to make several points here.

First, the value of a pointer to some type "T" -- i.e., a value of
type "T *" -- indeed possesses this "alignment" characteristic, so
that it is possible to ask whether such a pointer is correctly
aligned. (This question is inherently machine-dependent, however,
and on *some* machines it is meaningless.)

But note that if we store this pointer value in an object:

T *pointer_object;

we then have an *object*, not a variable. This object can have an
address:

T **p2 = &pointer_object;

(here the object's address is stored in yet another object, "p2",
of type "T **). If "pointer_object" has an address, that value --
a value of type "T **" -- *also* possesses this "alignment"
characteristic. Thus, we can ask not only whether the value stored
in "pointer_object" is correctly aligned, but also whether
"pointer_object" itself is correctly aligned. Having stored
&pointer_object in p2, we can then ask whether "the object p2" is
correctly aligned, via this question:

"does &p2 satisfy its machine-dependent alignment constraints?"

and if we store &p2 in yet another object:

T ***p3 = &p2;

we can then go on to ask whether "the object p3" (or more precisely,
the value produced by &p3) is correctly aligned, and so on.

There are thus four possible machine-dependent alignment constraints
arising so far:

(1) the value stored in pointer_object (of type "T *")
(2) the value produced by &pointer_object (type "T **")
(3) the value produced by &p2 (type "T ***")
(3) the value produced by &p3 (type "T ****")

and it makes some sense to ask whether all of them are satisified,
and to ask whether any or all four of these machine-dependent
alignment constraints are identical. Some of the answers are of
course machine-dependent. Since the objects named "pointer_object",
"p2", and "p3" are allocated by the compiler, they had better be
correctly aligned -- the C programmer is not the one responsible
for this -- but the rest of the answers require looking at the
machine.

For a number of existing, even common, machines today, the alignment
constraints for "T *" and "T **" often differ, depending on T.
For instance, "char *" always, by definition, needs only 1-byte
alignment ("C byte", not necessarily 8-bit-octet, although the
machines I am thinking of happen to have 8-bit C bytes too); but
"char **" often requires 4 or 8 byte alignment (32-bit or 64-bit
SPARC and MIPS, for instance).

Now, given the original example, or something at least close to
it:

struct C { char c; };
struct D { double d; };

you will find that, e.g., SPARC systems have sizeof(struct C) == 1
and align "struct C" objects on byte boundaries, while sizeof(struct D)
== 8 and "struct D" objects are always found on 8-byte boundaries.
Nonetheless, on those machines in 32-bit mode (or always for V8 and
earlier SPARC systems), "struct C *" and "struct D *" objects
are always aligned on 4-byte boundaries. In other words, given:

struct C *p1, **p2;
... set p1 and p2 ...

we can test the "alignment validity" (on that SPARC machine, in a
machine-dependent manner) with:

int is_p1_aligned(void) {
/* p1 is always properly aligned */
return 1;
}

int is_p2_aligned(void) {
/* p2 is properly aligned if and only if its low 2 bits are 0 */
return ((int)p2 & 3) == 0;
}

If we add "struct D *p3", however, the "is_p3_aligned" test becomes:

int is_p3_aligned(void) {
/* p3 is properly aligned if and only if its low 3 bits are 0 */
return ((int)p3 & 7) == 0;
}

Thus, the "aligned-ness" of a pointer depends on its type as well as
its value; and for two "struct T1 *" and "struct T2 *" values, the
"aligned-ness" of those two value may require different tests.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #20

P: n/a
"S.Tobias" <sN*******@amu.edu.pl> writes:
Keith Thompson <ks***@mib.org> wrote:
For example, a pointer object might require 4-byte alignment, whereas
a char object requires only 1-byte alignment. When the standard says
void* and char* have to have the same alignment requirements, the
intent is that they're interchangeable as arguments to functions.


Right.
extern char *pc;
void free(void *p);
free(pc); //correct

(Note: we don't need same representation requirement in the above
example. This requirement is necessary eg. for variadic arguments:
printf("%p", pc);
- no cast to void* required.)
Requiring 1-byte alignment for char* but only 4-byte alignment for
void* could break this.


No. I see no reason to require same alignment for types void* and char*,
because in function arguments they're passed by *value* (think conversion).
Similarly, long and char do not have to have same alignment, but we may
always use them in arguments "interchangeably":
extern long l;
extern char c;
int f_char(unsigned char c);
int f_long(unsigned long l);
f_char(l); //both calls correct
f_long(c);


No, we can't use long and char in arguments interchangeably. If
there's a prototype, the value is converted to the expected type;
you're not passing a char to f_long, you're passing a long. If
there's no visible prototype, the call f_long(c) invokes undefined
behavior.

Examples involving implicit conversions aren't relevant to the point.
In the call free(pc) above, you're not passing a char* to free(),
you're passing a void* value, the result of the implicit conversion of
the value of pc.

The interchangeability referred to in the footnote in C99 6.2.5
involves cases where something of one type is interpreted as another,
without a conversion (either explicit or implicit), such as a function
call with no prototype in scope, a call to a variadic function, or a
reference to a union member.

Suppose void* required 4-byte (word) alignment, but char* only
required 1-byte alignment (I'm referring to the required alignment for
a pointer object). Suppose the compiler has to generate different
code to access a byte-aligned char* than a word-aligned void*. Now
consider your call printf("%p", pc), where pc is a char*. The calling
code pushes the value of pc onto the stack at an odd address (assume
that there is a stack). The code inside printf that accesses the
argument expects a void*, so it uses an instruction that only works on
word-aligned values. Kaboom.

That's how differing alignments for void* and char* can cause problems
in parameter passing.

[snip]

(I'm not responding to the rest of your message, at least for now,
mostly because I don't have time to do it justice.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #21

P: n/a
Christian Kandeler <ch****************@hob.de_invalid> writes:
S.Tobias wrote:
I'm sorry, but I can't see how can you define a pointer to anonymous
struct in the first place (since that struct has no name).


struct {
int a;
int b;
} *pointer_to_anonymous_struct;


I suspect (but I'm only guessing) that the reference to "anonymous
structs" was actually meant to refer to incomplete types, such as

#include <stdio.h>
int main(void)
{
struct incomplete *ptr;
printf("sizeof ptr = %d\n", (int)sizeof ptr);
return 0;
}

The compiler has to determine the representation of ptr without
knowing anything about "struct incomplete" except that it's a struct.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #22

P: n/a
Chris Torek <no****@torek.net> writes:
In article <news:2r*************@uni-berlin.de>
S.Tobias <sN*******@amu.edu.pl> wrote:
[much snippage]
The last manner is also found in: 6.3.2.3#7 (Pointers) and 7.20.3#1
(Memory management functions). See for yourself: in both cases "pointer
alignment" refers to the pointer *value*, not pointer type.


I am not going to address most of this (due to lack of time), but
I want to make several points here.

First, the value of a pointer to some type "T" -- i.e., a value of
type "T *" -- indeed possesses this "alignment" characteristic, so
that it is possible to ask whether such a pointer is correctly
aligned. (This question is inherently machine-dependent, however,
and on *some* machines it is meaningless.)

But note that if we store this pointer value in an object:

T *pointer_object;

we then have an *object*, not a variable. This object can have an
address:

T **p2 = &pointer_object;

[...]

Chris, did you mean to write that we have an object, not a *value*?
(T is both an object and a variable.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #23

P: n/a
"S.Tobias" wrote:
.... snip ...
(Note: we don't need same representation requirement in the above
example. This requirement is necessary eg. for variadic arguments:
printf("%p", pc);
- no cast to void* required.)


On the contrary, that statement specifically requires a cast to
void*, unless pc is already of type void*.

--
"It is not a question of staying the course, but of changing
the course" - John Kerry, 2004-09-20
"Ask any boat owner the eventual result of continuing the
present course indefinitely" - C.B. Falconer, 2004-09-20
Nov 14 '05 #24

P: n/a
CBFalconer <cb********@yahoo.com> writes:
"S.Tobias" wrote:

... snip ...

(Note: we don't need same representation requirement in the above
example. This requirement is necessary eg. for variadic arguments:
printf("%p", pc);
- no cast to void* required.)


On the contrary, that statement specifically requires a cast to
void*, unless pc is already of type void*.


That's questionable, IMHO.

As a matter of style, I would always cast the argument to void* rather
than depend on an ambiguous guarantee of compatibility. But C99
6.2.5p26 says:

A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.

and a footnote says:

The same representation and alignment requirements are meant to
imply interchangeability as arguments to functions, return values
from functions, and members of unions.

I'm not convinced that requiring the same representation and alignment
requirements is really enough to guarantee that printf("%p", pc); will
actually work (where pc is a char*), but that does seem to be the
intent -- and I'd be surprised if there were an actual C90 or C99
implementation on which it doesn't work. (Making it break would
require some perversity on the part of the implementer.)

On the other hand, there are no guarantees regarding
printf("%p", pi);
where pi is of type int*; void* and int* could have different
representations.

(I assume that pc and pi have valid values.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #25

P: n/a
On Fri, 24 Sep 2004 18:51:13 GMT
Keith Thompson <ks***@mib.org> wrote:
Christian Kandeler <ch****************@hob.de_invalid> writes:
S.Tobias wrote:
I'm sorry, but I can't see how can you define a pointer toanonymous> struct in the first place (since that struct has no name).
struct {
int a;
int b;
} *pointer_to_anonymous_struct;


I suspect (but I'm only guessing) that the reference to "anonymous
structs" was actually meant to refer to incomplete types, such as


Yes. I was having a bad day.
The compiler has to determine the representation of ptr without
knowing anything about "struct incomplete" except that it's a struct.


Indeed.
--
Flash Gordon
Sometimes I think shooting would be far too good for some people.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #26

P: n/a
Keith Thompson <ks***@mib.org> wrote:
Examples involving implicit conversions aren't relevant to the point.
True, I missed it. Now that you later mention it, I guess (I'm not
a historian) that long ago when there was no void type, the function
declarations didn't have prototypes either, so the declarations for
free and memcpy were:
free();
free(p) char *p; {...}
char *memcpy();
char *memcpy(d, s, n) char *d, *s; size_t n; {...}
And this is probably the interchangeability in arguments that the
Rationale refers to, ie. that we may may pass the newer void* arguments
to old library functions which expect char*, right?
Therefore internally it is required that newer void* type have at
least the alignment requirement of older char* type in function calls
and returns (it still means nothing in context of our discussion, the
programmer need not know about this), and of course same representation.
[ I think CBFalconer rightfully noticed that the argument in the call:
extern char *pc;
printf("%p", pc);
should be cast to type void* (strictly interpreting the description at
the fprintf() function).
My intention was to discuss argument passing in variadic functions. So,
for the purpose of the discussion, let's assume that printf is actually a
user defined function which duplicates standard library printf behaviour,
and which internally uses va_* macros from stdarg.h. (We can rename it
to my_printf() if you insist.) ]
The interchangeability referred to in the footnote in C99 6.2.5
involves cases where something of one type is interpreted as another,
without a conversion (either explicit or implicit), such as a function
call with no prototype in scope, a call to a variadic function, or a
reference to a union member.
For unions there is no problem: both types have same representation (we
agree to it), and the union itself accommodates alignment requirements
of all its members.
Suppose void* required 4-byte (word) alignment, but char* only
required 1-byte alignment (I'm referring to the required alignment for
a pointer object). Suppose the compiler has to generate different
code to access a byte-aligned char* than a word-aligned void*. Now
consider your call printf("%p", pc), where pc is a char*. The calling
code pushes the value of pc onto the stack at an odd address (assume
that there is a stack). The code inside printf that accesses the
argument expects a void*, so it uses an instruction that only works on
word-aligned values. Kaboom.
It's a nice explanation (really). But:
7.15.1#2 for variadic functions (and similarly 6.5.2.2#6 for functions
without prototype) makes special provision for void* and char* types.
In order to fulfill it the compiler, when creating a function call, *must*
push char* (void*) argument in such a way, that it may be accessed as
void* (char*) argument. (In practice that would mean taking at least
the least common multiple of both types' alignments.)

So, your example still doesn't prove that char* and void* types must
have the same alignment, or that the programmer needs know about it.

Moreover, passing and argument which is incompatible with parameter
(or expected) type, is *explicitly* deemed UB. There is no discussion
that we may pass "struct s1*" to where we expect "struct s2*", because
their alignments are the same (as you interpret it) and so are their
representations. They are incompatible types and it is undefined, period.
(If your interpretation is really right, then there must be a flaw in
the Standard here.)

Therefore, again, there is nothing a programmer gains here by knowing
that "pointer to struct" types have same alignment.

[snip] (I'm not responding to the rest of your message, at least for now,
mostly because I don't have time to do it justice.)


No hurry, I'll be waiting. You'll do me a favour.

But maybe there is no point in discussing everything at once. In order
to convince me to what is after "Similarly", first you have to convince
me to what the Standard means before the word. I still don't see why
void* and char* types should have the same alignment requirements,
and that the Standard actually requires it at all.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #27

P: n/a
Dan Pop <Da*****@cern.ch> wrote:
struct { ... } foo, bar, baz; foo, bar and baz are all the objects of this type needed by the program
and they are used in a single translation unit. What would a tag buy you?


I think we're talking of two different things. I used the definition
of an anonymous union I found in:
http://docs.sun.com/source/816-2460/...xtensions.html

Never mind.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #28

P: n/a
S.Tobias <sN*******@amu.edu.pl> wrote:
I think we're talking of two different things. I used the definition
of an anonymous union I found in:

^^^^^ -> struct
(sorry, it's late)

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #29

P: n/a
"S.Tobias" <sN*******@amu.edu.pl> writes:
[big snip (sorry)]
But maybe there is no point in discussing everything at once. In order
to convince me to what is after "Similarly", first you have to convince
me to what the Standard means before the word. I still don't see why
void* and char* types should have the same alignment requirements,
and that the Standard actually requires it at all.


Just a quick thought. It's entirely possible that the standard is
over-specified in this area, and that there's no real advantage in
requiring void* and char* to have the same representation and
alignment requirements. (I'd have to spend some time thinking about
it to decide whether that's the case or not.) Even so, C99 6.2.5p26
does require them to have the same representation and alignment
requirements, at least according to my interpretation of the text.

In order for this to refer to the alignment of what they point to,
rather than the alignment of the pointer objects themselves, we'd have
to assume that in the phrase "the same representation and alignment
requirements", "representation" refers to the pointers (since there is
no representation for void), and "alignment requirements" refers to
the alignment of what's being pointed to. I suppose that's not
entirely unreasonable, since even in this sense the "alignment
requirements" of a pointer are arguably a property of the pointer
itself.

But we already know the alignment requirements of what void* and char*
point to: both types have to be able to refer to any byte in any
object. An additional explicit statement to that effect in 6.2.5p26
would be logically redundant (rather than just possibly unnecessary).
The only way 6.2.5p26 makes sense to me is if it refers to the
alignment requirements for char* and void* objects, not for what they
point to.

Here's a (rather silly) program that, I believe, is guaranteed to work
given the requirement in 6.2.5p26, and wouldn't be guaranteed to work
without it:

#include <stdio.h>
int main(void)
{
char obj;
char *c_ptr = &obj;
void *v_ptr;

v_ptr = *((void**)&c_ptr);

printf("c_ptr = %p\n", (void*)c_ptr);
printf("v_ptr = %p\n", v_ptr);
return 0;
}

It assigns the value of c_ptr to v_ptr by pretending that there's a
void* pointer object in the location of c_ptr. There's no char* to
void* conversion, implicit or explicit, so the compiler doesn't have a
chance to allow for any difference in representation or alignment. If
we used an int* rather than a char*, 6.2.5p26 wouldn't apply and we'd
have undefined behavior; int* and void* needn't even be the same size.

(gcc with too many warnings enabled complains that "dereferencing
type-punned pointer will break strict-aliasing rules".)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #30

P: n/a
Keith Thompson <ks***@mib.org> wrote in message news:<ln************@nuthaus.mib.org>...
Flash Gordon <sp**@flash-gordon.me.uk> writes:
On 23 Sep 2004 19:10:38 GMT
"S.Tobias" <sN*******@amu.edu.pl> wrote:
I would like to check if I understand the following excerpt correctly:

6.2.5#26 (Types):
All pointers to structure types shall have the same representation
and alignment requirements as each other. All pointers to union
types shall have the same representation and alignment requirements
as each other.

Does it mean that *all* structure (or union) types have the same
alignment?
Eg. type
struct { char c; }
and
struct { long double ldt[11]; }
have the same alignment requirements?
Yes. Think about what what has to be done to implement pointers to
anonymous structs. When the compiler is compiling a piece of code that
increments a pointer to an anonymous struct all it knows is that it is a
pointer to a struct, so how else could this have been done?


When 6.2.5 discusses the alignment requirements of various types, it's
clear that it's referring to the alignment of objects of the type
itself. It uses similar wording in 6.2.5p26, so I think it's
referring to the alignment of a pointer object, not the alignment of
what it points to.


Correct.

<snip>

I believe that an implementation in which pointer values are simple
byte addresses, small structs (struct { char c; }) have, say, 1-byte
alignment, and larger structs have, say, 4-byte alignment could be
conforming. Can you think of a concrete example where this would
cause problems?

No, that will not cause any problems. Many implementations do this,
including the one I'm typing this response from.

<snip> Assume in the following that sizeof(int) == 4.

On some hardware, an int can be accessed more efficiently if it's
aligned on a 4-byte boundary, but can still be accessed if it's merely
byte-aligned. An implementation could consistently choose to align
all declared int objects on 4-byte boundary, but use byte alignment
for struct members that are of type int (to save space). Or vice
versa.

I'm not saying that this would be a sensible thing to do, but it's
legal.
Right. It's an ABI issue, and many compilers have command line
switches that determine which ABI they target.

A quick example:

-malign-double
-mno-align-double
Control whether GCC aligns double, long double, and long long
variables on a two word boundary or a one word boundary. Aligning
double variables on a two word boundary will produce code that
runs somewhat faster on a Pentium at the expense of more memory.

Warning: if you use the -malign-double switch, structures cont-
aining the above types will be aligned differently than the
published application binary interface specifications for the 386
and will not be binary compatible with structures in code compiled
without that switch.

I suppose we're talking about two different meanings of "alignment
requirements": the alignment the compiler chooses to use for a given
type, and the alignment that's actually required by the hardware. The
former needs to be at least as strict as the latter, but it needn't be
the same.


Not necessarily, because the compiler is free to do byte loads of
unaligned types. For example, you may be able to tell your compiler
to use no padding in any struct type.
Mark F. Haigh
mf*****@sbcglobal.net
Nov 14 '05 #31

P: n/a
Keith Thompson <ks***@mib.org> wrote:
In order for this to refer to the alignment of what they point to,
rather than the alignment of the pointer objects themselves, we'd have
to assume that in the phrase "the same representation and alignment
requirements", "representation" refers to the pointers (since there is
no representation for void), and "alignment requirements" refers to
the alignment of what's being pointed to. I suppose that's not
entirely unreasonable, since even in this sense the "alignment
requirements" of a pointer are arguably a property of the pointer
itself. But we already know the alignment requirements of what void* and char*
point to: both types have to be able to refer to any byte in any
object. An additional explicit statement to that effect in 6.2.5p26
would be logically redundant (rather than just possibly unnecessary).
The only way 6.2.5p26 makes sense to me is if it refers to the
alignment requirements for char* and void* objects, not for what they
point to.


I think there is sense in talking about pointed to type requirements.

When we say that (the values of) "pointer to TYPE" have alignment
requirements, we establish set of valid values of the pointer type,
ie. some are valid pointer values (aligned), some are not (not aligned).
This automatically implies same requirement for placement of objects
of type TYPE, and also includes cases where a pointer might not point
to an object (NULL, end of array, malloc(0)), or TYPE is not complete.
(It is simply easier to speak of "pointer to TYPE (values)" alignment,
that "TYPE (object)" alignment, because it is more inclusive.)

I think that what the Standard does in 6.2.5p26 is that it formulates
set of valid values for type void* : they are valid/invalid, whenever
same value (thanks to same representation) of type char* is valid/invalid.

Invalid value of type void* could be created by casting from an integer.

And yes, I think char type can have alignment issues. Consider this
setup: Type char is composed of 4 octets. Type char* or void* is
the memory index of an octet where an object starts. The C language
conceptual model requires char objects to be on 4-octet boundary, and
so for char* values. I think it is clear, that not requiring the same
for void* values would break everything.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #32

P: n/a
S.Tobias <sN*******@amu.edu.pl> wrote:
The C language
conceptual model requires char objects to be on 4-octet boundary, and


Well, not exactly C language, but for any purpose we can assume
that this alignment is required throughout the whole memory core
(by hardware, or merely by the implementation itself).

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #33

P: n/a
>Chris Torek <no****@torek.net> writes:
... a pointer to some type "T" ... But note that if we store this pointer value in an object:
T *pointer_object;
we then have an *object*, not a variable. This object can have an
address:
T **p2 = &pointer_object;[...]

In article <news:ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> wrote:Chris, did you mean to write that we have an object, not a *value*?
(T is both an object and a variable.)


T is a type-name (e.g., "typedef int T;" for instance -- or just
replace T with some simple type like char or int or double). Did
you mean "p2" rather than T here? I deliberately wanted p2 to be
an object holding a value of type "T **", so that I could then take
its address as well.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #34

P: n/a
Chris Torek <no****@torek.net> writes:
Chris Torek <no****@torek.net> writes:
... a pointer to some type "T" ... But note that if we store this pointer value in an object:
T *pointer_object;
we then have an *object*, not a variable. This object can have an
address:
T **p2 = &pointer_object;

[...]

In article <news:ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> wrote:
Chris, did you mean to write that we have an object, not a *value*?
(T is both an object and a variable.)


T is a type-name (e.g., "typedef int T;" for instance -- or just
replace T with some simple type like char or int or double). Did
you mean "p2" rather than T here? I deliberately wanted p2 to be
an object holding a value of type "T **", so that I could then take
its address as well.


D'oh! Yes, I meant to say that p2 is both an object and a variable.

So, did you mean "we then have an *object*, not a variable", or did
you mean "we then have an *object*, not a value"?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #35

P: n/a
S.Tobias wrote:
And yes, I think char type can have alignment issues. Consider this
setup: Type char is composed of 4 octets.


What are you talking about?
sizeof(char) is one, always.

--
pete
Nov 14 '05 #36

P: n/a
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
And yes, I think char type can have alignment issues. Consider this
setup: Type char is composed of 4 octets.
What are you talking about?
sizeof(char) is one, always. --
pete


--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #37

P: n/a
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
And yes, I think char type can have alignment issues. Consider this
setup: Type char is composed of 4 octets.
What are you talking about?
sizeof(char) is one, always.


Yes, I didn't say it's not. sizeof(char)==1, CHAR_BIT==32, and on
C level you can access objects only with byte-resolution (ie. char).
The implementation must hide the sub-byte world from the programmer.
But I think it would be allowed to use hardware representation for
char*, which happens to be pointer to (index of) the first octet of the
pointed-to object (char in our case). When we add one to char* value,
this octet pointer (index) jumps by four. Conversions between char* and
an integer type just preserve and copy this value. Valid values of the
type char* might be 0x0, 0x4, 0x8, 0xc... etc. (char*)3 is a pointer
to char, but is invalid, because is not aligned properly to char type.

I think there is no problem with above implementation. The Standard
I believe doesn't put any restrictions on pointer representation,
and never says that char shall have no alignment.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #38

P: n/a
S.Tobias wrote:

pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
And yes, I think char type can have alignment issues.
Consider this
setup: Type char is composed of 4 octets.

What are you talking about?
sizeof(char) is one, always.


Yes, I didn't say it's not. sizeof(char)==1, CHAR_BIT==32, and on
C level you can access objects only with byte-resolution (ie. char).
The implementation must hide the sub-byte world from the programmer.
But I think it would be allowed to use hardware representation for
char*, which happens to be pointer to (index of)
the first octet of the
pointed-to object (char in our case). When we add one to char* value,
this octet pointer (index) jumps by four.
Conversions between char* and
an integer type just preserve and copy this value.
Valid values of the
type char* might be 0x0, 0x4, 0x8, 0xc... etc. (char*)3 is a pointer
to char, but is invalid, because is not aligned properly to char type.

I think there is no problem with above implementation. The Standard
I believe doesn't put any restrictions on pointer representation,
and never says that char shall have no alignment.


I'm still not understanding what you're saying.
If a char has the same representation as char*,
and sizeof(char*) is 4, then,
is each byte of the four bytes of your char*,
also composed of 4 octets?

Do you think a pointer to char should have any trouble
stepping through all the bytes of an object of type pointer to char?

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
char *object, *pointer;
size_t n;

n = sizeof object;
object = NULL;
pointer = (char *)&object;
while (n-- != 0) {
printf("byte = 0x%x\n", *(unsigned char *)pointer);
pointer++;
}
return 0;
}

/* END new.c */

I don't understand what alignment problems
you think that there can be.

--
pete
Nov 14 '05 #39

P: n/a
[I wrote, in part]
But note that if we store this pointer value in an object:
T *pointer_object;
we then have an *object*, not a variable. This object can have an
address:
T **p2 = &pointer_object;
[...]

After a bit of confusion on both our parts, in
article <news:ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> wrote:D'oh! Yes, I meant to say that p2 is both an object and a variable.

So, did you mean "we then have an *object*, not a variable", or did
you mean "we then have an *object*, not a value"?


Ah, I see my error now. Yes, the second phrase is what I meant to
type in, but even that is not quite right either: what we have is
an object with no initial value. :-) The variable named "pointer_object"
is indeed an object.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #40

P: n/a
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
Yes, I didn't say it's not. sizeof(char)==1, CHAR_BIT==32, and on
C level you can access objects only with byte-resolution (ie. char).
The implementation must hide the sub-byte world from the programmer.
Afterthought: the implementation actually need not try to hide it.
It might even allow accessing objects with sub-byte resolution.
But this is implementation defined, and undefined by the standard.

Since void* does not point to any object, is a "free pointer",
the Standard must specify that the void* values which are valid
for char*, are also valid for void*, otherwise undefined. And
this is what a programmer must be concerned about.
But I think it would be allowed to use hardware representation for
char*, which happens to be pointer to (index of)
the first octet of the
pointed-to object (char in our case). When we add one to char* value,
this octet pointer (index) jumps by four.
Conversions between char* and
an integer type just preserve and copy this value.
Valid values of the
type char* might be 0x0, 0x4, 0x8, 0xc... etc. (char*)3 is a pointer
to char, but is invalid, because is not aligned properly to char type.

I think there is no problem with above implementation. The Standard
I believe doesn't put any restrictions on pointer representation,
and never says that char shall have no alignment.

I'm still not understanding what you're saying.
The implementation defines byte (char) not what the machine thinks
is a byte (I used name "octet" for machine-bytes). Everything
else is built of bytes.
(I hope my use of the word "octet" is not improper, it wasn't reserved
by the Standard.)
If a char has the same representation as char*,
No, I didn't say that, it's nonsense. All I said is that the
implementation uses machine representation of pointer for char* (and
possibly for other pointer types). Of course, this machine representation
must be composed of multiple of 4-octets (or padded up to that boundary),
so that a pointer type object may be accessed as char array.
and sizeof(char*) is 4, then,
It might be any value. If it's 4, then char* object takes 4 bytes
(or 16 octets, in machine speak).
is each byte of the four bytes of your char*,
also composed of 4 octets?
Of course. On C level everything is built of bytes.
Do you think a pointer to char should have any trouble
stepping through all the bytes of an object of type pointer to char? /* BEGIN new.c */ #include <stdio.h> int main(void)
{
char *object, *pointer;
size_t n; n = sizeof object;
object = NULL;
pointer = (char *)&object;
while (n-- != 0) {
printf("byte = 0x%x\n", *(unsigned char *)pointer);
pointer++;
}
return 0;
} /* END new.c */
I see no problem.
I don't understand what alignment problems
you think that there can be.


pointer = (char*)((unsigned)(char*)&object + 2)
points into the middle of a byte and is not a valid value for a pointer.
Undefined, but for some reason implementation might allow it.

Could there be any conflict with the Standard? (I'm asking, I'm not
completely sure myself.)

Perhaps my use of the word "alignment" was an abuse. I read
now in 3.2 that the Standard defines alignment only with respect
to byte-resolution, where I rather meant sub-byte. I saw a similarity
in that as you can access an object as int for only specific (aligned)
values of int*, in the same manner you can access (in my example)
an object as type char only for specific values of char*.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #41

P: n/a
S.Tobias wrote:
Since void* does not point to any object, is a "free pointer",
the Standard must specify that the void* values which are valid
for char*, are also valid for void*, otherwise undefined. And
this is what a programmer must be concerned about.


void* can hold the address of any byte of any object, just like char*.

N869
6.3.2.3 Pointers
[#1] A pointer to void may be converted to or from a pointer
to any incomplete or object type. A pointer to any
incomplete or object type may be converted to a pointer to
void and back again; the result shall compare equal to the
original pointer.

6.2.5 Types
[#27] A pointer to void shall have the same representation
and alignment requirements as a pointer to a character type.

--
pete
Nov 14 '05 #42

P: n/a
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
Since void* does not point to any object, is a "free pointer",
the Standard must specify that the void* values which are valid
for char*, are also valid for void*, otherwise undefined. And
this is what a programmer must be concerned about.
void* can hold the address of any byte of any object, just like char*.
And which address void* in my example implementation cannot hold?

Valid int* values are determined (among others) by int type object
alignment requirements; char* - by char alignment, void* - by what?
By void object alignment? It doesn't make sense. Therefore
we have to set alignment requirements for values same as in char*.

(Note, that here I'm using the word valid/invalid not in the sense
of in/valid values (like trap representation), but in the sense
of un/defined behaviour. Ie. use of invalid pointer is undefined,
but the Standard does not forbid an implementation to define it.)
N869
6.3.2.3 Pointers
[#1] A pointer to void may be converted to or from a pointer
to any incomplete or object type. A pointer to any
incomplete or object type may be converted to a pointer to
void and back again; the result shall compare equal to the
original pointer.
#7 adds to this provisions for alignment requirements. If you convert a
char* to an int*, and the pointer is not aligned for int, the behaviour
is undefined. The implementation might abort on the very moment of
attempt of such conversion, without even completing it.

Similarly, when you convert, say, an int* to void*, how do you know
that the result fulfills alignment requirements? Or when you convert
an integer to void*? When is the implementation allowed to abort
and when not?

My hypothesis is that in 6.2.5#26 the Standard formulates these
alignment requirements for (values of) void*. The implementation
is not allowed to abort when the result is aligned to type char,
otherwise it may.

At the same time it does not forbid the implementation to allow other
pointer values (eg. sub-byte resolution), it's just that it's undefined,
ie. outside the domain of interest of the Standard.
6.2.5 Types (6.2.5#26 in the Std) [#27] A pointer to void shall have the same representation
and alignment requirements as a pointer to a character type.

^^^^^^^^^^^^^^^^^^^^^^

And this is what this sub-sub-subdiscussion was about when you asked
your question: whether "alignment requirements" refers to the values
of the pointer (or, to what the pointer points to), or to the pointer
object itself. I try to prove that talking at this point of the values
of type void* is not nonsensical (it is not a proof by itself what the
Standard actually means there, though). Others think it refers to the
objects of type void*, but it is still not clear why. (I have to yet
think over Keith's example program closely.)

===

And one more thought concerning nomenclature, which I think is pretty
obvious, but might be useful to express:

Types have "alignment properties" which impose "alignment requirements"
on pointers to them (ie. what values they can hold, or how the values
can be used).

(Disclaimer: with the above remark I'm not trying to prove anything;
in fact if I did, it would act against my hypothesis. I think that the
Standard's use of words is sloppy and I feel it's good to straighten
things up sometimes.)

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #43

P: n/a
S.Tobias wrote:

pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
Since void* does not point to any object, is a "free pointer",
the Standard must specify that the void* values which are valid
for char*, are also valid for void*, otherwise undefined. And
this is what a programmer must be concerned about.
void* can hold the address of any byte of any object,
just like char*.


And which address void* in my example implementation cannot hold?


I don't understand your question.
Valid int* values are determined (among others) by int type object
alignment requirements; char* - by char alignment, void* - by what?
By void object alignment? It doesn't make sense. Therefore
we have to set alignment requirements for values same as in char*.

(Note, that here I'm using the word valid/invalid not in the sense
of in/valid values (like trap representation), but in the sense
of un/defined behaviour. Ie. use of invalid pointer is undefined,
but the Standard does not forbid an implementation to define it.)
N869
6.3.2.3 Pointers
[#1] A pointer to void may be converted to or from a pointer
to any incomplete or object type. A pointer to any
incomplete or object type may be converted to a pointer to
void and back again; the result shall compare equal to the
original pointer.
Similarly, when you convert, say, an int* to void*, how do you know
that the result fulfills alignment requirements?
The standard says so.
You must be reading 6.3.2.3 differently from the way that I read it.
Or when you convert
an integer to void*?


Conversion between pointers and integers is implementation defined.
There's nothing in the standard preventing
the addresses of four consecutive bytes
from converting to three odd numbers and an even one.

--
pete
Nov 14 '05 #44

P: n/a
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:

> Since void* does not point to any object, is a "free pointer",
> the Standard must specify that the void* values which are valid
> for char*, are also valid for void*, otherwise undefined. And
> this is what a programmer must be concerned about.
void* can hold the address of any byte of any object,
just like char*.


And which address void* in my example implementation cannot hold? I don't understand your question.
I asked because I didn't understand where to apply your statement to.
Perhaps, never mind.

N869
6.3.2.3 Pointers
[#1] A pointer to void may be converted to or from a pointer
to any incomplete or object type. A pointer to any
incomplete or object type may be converted to a pointer to
void and back again; the result shall compare equal to the
original pointer.
Similarly, when you convert, say, an int* to void*, how do you know
that the result fulfills alignment requirements? The standard says so.
Where?
You must be reading 6.3.2.3 differently from the way that I read it.
I think that the difference between our reading of 6.3.2.3 may be
that you might assume that #1 demands that conversions to and from
void* must always succede. IMO if that were the case, then all
conversions from void* to unaligned int* would have to complete
without a cough. I think this is not what the Standard requires.

#7 adds alignment provisions, and does not exclude void* types.

(In fact, I don't see why #1 is even neccessary. Or am I wrong?)
Or when you convert
an integer to void*?

Conversion between pointers and integers is implementation defined.
There's nothing in the standard preventing
the addresses of four consecutive bytes
from converting to three odd numbers and an even one.


But if the implementation wishes to map integers exactly into pointers
and documents it so, then after conversion the Standard does apply.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #45

P: n/a
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
And yes, I think char type can have alignment issues. Consider this
setup: Type char is composed of 4 octets.


What are you talking about?
sizeof(char) is one, always.


So? Byte != octet.

Richard
Nov 14 '05 #46

P: n/a
S.Tobias wrote:

pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
pete <pf*****@mindspring.com> wrote:
> S.Tobias wrote:
>
> > Since void* does not point to any object, is a "free pointer",
> > the Standard must specify that the void* values which are valid
> > for char*, are also valid for void*, otherwise undefined. And
> > this is what a programmer must be concerned about.

> void* can hold the address of any byte of any object,
> just like char*.

And which address void* in my example implementation cannot hold?
I don't understand your question.
I asked because I didn't understand where to apply your statement to.
Perhaps, never mind.
N869
> 6.3.2.3 Pointers
> [#1] A pointer to void may be converted to or from a pointer
> to any incomplete or object type. A pointer to any
> incomplete or object type may be converted to a pointer to
> void and back again; the result shall compare equal to the
> original pointer. Similarly, when you convert, say, an int* to void*, how do you know
that the result fulfills alignment requirements?

The standard says so.


Where?
You must be reading 6.3.2.3 differently from the way that I read it.


I think that the difference between our reading of 6.3.2.3 may be
that you might assume that #1 demands that conversions to and from
void* must always succede. IMO if that were the case, then all
conversions from void* to unaligned int*
would have to complete
without a cough. I think this is not what the Standard requires.


If you have an unaligned int*, then you are invoking
undefined behavior and you code is no longer C code.
The rules don't apply after that.
(In fact, I don't see why #1 is even neccessary.


That doesn't prove that you don't understand it, but it's a clue.

--
pete
Nov 14 '05 #47

P: n/a
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:
I think that the difference between our reading of 6.3.2.3 may be
that you might assume that #1 demands that conversions to and from
void* must always succede. IMO if that were the case, then all
conversions from void* to unaligned int*
would have to complete
without a cough. I think this is not what the Standard requires. If you have an unaligned int*, then you are invoking
undefined behavior and you code is no longer C code.
The rules don't apply after that.
int *ip;
char *cp;
void *vp;

cp = malloc(2 * sizeof(int));
cp++; //defined
vp = cp; //defined
ip = vp; //???
(In fact, I don't see why #1 is even neccessary.

That doesn't prove that you don't understand it, but it's a clue.


Maybe I don't. Would you, please, care to explain it to me.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #48

P: n/a
S.Tobias wrote:

pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:

I think that the difference between our reading of 6.3.2.3 may be
that you might assume that #1 demands that conversions to and from
void* must always succede. IMO if that were the case, then all
conversions from void* to unaligned int*
would have to complete
without a cough. I think this is not what the Standard requires.

If you have an unaligned int*, then you are invoking
undefined behavior and you code is no longer C code.
The rules don't apply after that.


int *ip;
char *cp;
void *vp;

cp = malloc(2 * sizeof(int));
cp++; //defined
vp = cp; //defined
ip = vp; //???


Assuming that sizeof(int) is greater than one,
ip = vp;
is not defined.

--
pete
Nov 14 '05 #49

P: n/a
pete <pf*****@mindspring.com> wrote:
S.Tobias wrote:

int *ip;
char *cp;
void *vp;

cp = malloc(2 * sizeof(int));
cp++; //defined
vp = cp; //defined
ip = vp; //???
Assuming that sizeof(int) is greater than one,
ip = vp;
is not defined.


Why?

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #50

67 Replies

This discussion thread is closed

Replies have been disabled for this discussion.