struct mapping problem (gcc on Linux)

N

Nick Keighley

None of those structures contain unaligned fields,

??
how do you know? What is an "unaligned field"?

so there is no reason for padding on any architecture.

why? You have examinied all possible computer architectures that could
support a C compiler?
 
N

Nick Keighley

This post is a good example of certain regulars' obsession with the
standard in preference to reality.

the fact that the standard provides no such support *is* reality.
And this attempt to magic up some rules for alignment is a denial
of what is actually so in the real world
Lots of real-world code gets written which isn't 100%-portable, and it
usually works.

and I've written a fair amount of it.
The language *standard* may not specify this behaviour.

and implementations don't provide this behaviour
Fortunately, most
of the C compilers in existence were written by people who are more
interested in practical use than in language-lawyering, so they
make the effort to let you do all this "invalid" stuff.

sometimes at enourmous cost (see else-thread on the ARM compiler)
 
J

James Kuyper

Phil said:
That can be the case only of the 80-bit floating point values are
padded to at least 96 or 128 bits, where the padding is actually
part of the object. C arrays cannot have gaps between elements.

As someone who uses 80-bit floats a lot, this is one thing that
narks me. It's a clear weakness in the C standard if it has to
force the implementation to lie about the size of an object when
I use sizeof, by telling me the size of the tile in which it fits
instead.

I'd like struct { long double f; char c[2]; } to fit in 12 bytes on
an x86, because in reality it does.

In other words, you don't mind if if is no longer the case that
sizeof(T[N]) == N*sizeof(T), where T is a type name and N is the
dimension of an array of that type. I suppose you could make an argument
for doing it differently in a new language, but it is of course way too
late to make such a change in C - there's far too much existing code
that relies upon that relationship being true.
 
N

Nobody

??
how do you know? What is an "unaligned field"?

A field which causes padding to be inserted to satisfy the alignment
constraints of its type.
why? You have examinied all possible computer architectures that could
support a C compiler?

No; I would have thought that it was clear that the above refers to the
architectures which Linux attempts to support (we were talking
specifically about a Linux kernel header).
 
N

Nobody

No, that's completely wrong, and I should know since it's my post
you're commenting on. So allow me to correct your statement above:

"This post is a good example of certain regulars' obsession with the
standard and topicality _IN_ comp.lang.c."

If it's C, then it's on-topic for clc, IMNSHO. Repeatedly asserting that
this group is reserved solely for the aspects of C which are specified by
the ISO standards doesn't make it so.
As for reality, 85% of all the C code I have written in more than 30
years has been in embedded systems, most of them real-time and
safety-critical. And all of them had a considerable amount of
non-standard, hardware-specific code,

Which is as much C as the standard, platform-independent code.
But I have the good sense not to discuss such issues here in c.l.c.,
because they are beyond the scope of the C language. I discuss
embedded systems issues in one or more groups such as
comp.arch.embedded, comp.realtime, comp.sys.arm, comp.dsp, and so on.

And when I have an issue with Windows programming, I ask in a group
such as
The OP had an issue with gcc on Linux not doing what he expected.
Whether he knew it or not, the C language standard can't help him
here, so he should be redirected to a group dealing with gcc on Linux.

Except that he would have had the same issues on Windows or MacOSX or a
freestanding implementation.

The real issue behind the OP's question wasn't alignment and packing on
Linux, or on x86 or on Linux/x86, but about alignment and packing per se.
Of course I could have replied indicating what to do with IAR for ARM,
or Code Composer Studio 2.21 for the TMS320F2812 (nothing, in the
latter case, because even 8-bit values occupy 16 bits of memory, and
CHAR_BIT is 16).

Then why didn't you? From the perspective of actually using C as a
programming language, knowlege of actual implementations is at least as
useful as knowledge of the standard, sometimes moreso.

[C is quite unusual in the extent to which implementations actually
conform to the standard. There are a lot of standards which are
effectively meaningless due to the complete absence of implementations
which actually conform; HTML would be a good example of this.]
Perhaps you weren't around about a dozen years ago when clueless
newbie posters turned comp.lang.c++ into a sewer of Windows API
questions, rendering it almost useless for discussing the actual C++
language. It took a determined effort by a handful of militant
regulars to take it back.

No. No, I wasn't. Perhaps that's why I don't spend my time fighting
imaginary demons.

If there's a threat to this group's utility, it isn't from its scope
being enlarged into a catch-all comp.programming, but from its scope being
reduced to the point where it's a club for a handful of language lawyers
discussing minutae, trivia and corner-cases, with anything related to
actual programming being deflected the moment someone even mentions the
name of one of their target platforms.
 
N

Nobody

In that case it's broken. A kernel should no less isolate non-portable
parts into one little corner of the code (perhaps as macros, so that
optimisations can still be done more easily) than any other application.

True enough, but bear in mind that most people tend to define "portable"
along the lines of "works with every implementation which we're willing
to support", and not "works with every standards-conformant
implementation, without exception".

A bug report that the Linux kernel doesn't isolate code which won't work
with a 16-bit "int" is likely to get closed as "not a bug".

[I don't know whether they support a 64-bit "int"; using __u32 only gets
you so far due to C's integral promotions.]
 
J

James Kuyper

Nobody said:
If it's C, then it's on-topic for clc, IMNSHO.

So, by that standard, if you're writing a C program to calculate batting
averages, asking questions in this newsgroup about the rules of baseball
is on-topic? That's fundamentally no different than writing a C program
making use of POSIX threads, and asking questions in this newsgroup
about the rules of POSIX threading.
Which is as much C as the standard, platform-independent code.

Yes, but a newsgroup devoted to the particular type of embedded system
such code is targeted for would be much more likely to have people who
could usefully discuss it.

....
Except that he would have had the same issues on Windows or MacOSX or a
freestanding implementation.

No, he would have different but similar issues in each of those cases;
the main thing they have in common with each other is that the C
standard allows for such issues to arise. That's not enough to justify
talking about them in a newsgroup not specific to the the particular
type of system he's actually interested in.
Then why didn't you? From the perspective of actually using C as a
programming language, knowlege of actual implementations is at least as
useful as knowledge of the standard, sometimes moreso.

Actually, that's not always the case. Since my code is supposed to be
run on a wide variety of systems, it's not particularly useful for me to
know anything about how any particular one of them defines things that
the standard leaves unspecified. It wouldn't hurt, but it wouldn't help
much, either.

However, I recognize that many programmers have less need for
portability than I do. In that case, discussion of those actual
implementations is more productive in forums devoted to them, rather
than in a more general forum, like this one.
If there's a threat to this group's utility, it isn't from its scope
being enlarged into a catch-all comp.programming, but from its scope being
reduced to the point where it's a club for a handful of language lawyers
discussing minutae, trivia and corner-cases, with anything related to
actual programming being deflected ...

I don't see any significant danger of that happening ...
... the moment someone even mentions the
name of one of their target platforms.

though that sounds like a wonderful idea. It's overkill, but it would
tend to discourage topics best discussed in some other forum.
 
N

Nobody

So, by that standard, if you're writing a C program to calculate batting
averages, asking questions in this newsgroup about the rules of baseball
is on-topic?

[Here come the strawmen again.]

Nope. Asking questions about baseball isn't on-topic. But questions about
structuring data (where the data happens to be batting scores) might be.
As the discussion progresses, pointing out that a proposed data structure
doesn't allow for some obscure baseball rule might also be on-topic.
That's fundamentally no different than writing a C program
making use of POSIX threads, and asking questions in this newsgroup
about the rules of POSIX threading.

If you were only asking about the semantics of the POSIX threading API,
then it wouldn't be on-topic.

But if you're writing multi-threaded code in C, that brings up a whole
load of issues about load/store semantics, "volatile", etc, and most of
the useful information is specific to a particular architecture, compiler,
or threading library.

Trying to isolate different parts of the discussion into
architecture-specific, compiler-specific, OS-specific etc portions would
be impractical. And for what benefit? To satisfy specific posters' notions
of topicality?

I'm well aware that a lot of programmers (particularly from the MS sphere)
don't make the distinction between the API and the language, but the
distinction isn't always that clear-cut. Threading is a good example of
where it isn't; garbage-collection is another.
Yes, but a newsgroup devoted to the particular type of embedded system
such code is targeted for would be much more likely to have people who
could usefully discuss it.

That's fine if you're only interested in one specific system. Often, the
platform on which code is being developed is just the one which is most
immediately at hand. Particularly for embedded systems, where you
often choose one specific hardware platform (possibly a custom platform)
to suit the application.
...

No, he would have different but similar issues in each of those cases;
the main thing they have in common with each other is that the C
standard allows for such issues to arise. That's not enough to justify
talking about them in a newsgroup not specific to the the particular
type of system he's actually interested in.

IOW, someone who is interested in multiple targets is supposed to ask on
several different groups (where slightly different versions of the same
information will be imparted on each, and "this is better for platform X
but worse for platform Y" isn't on-topic anywhere in the whole of usenet,
presumably).
 
B

Beej Jorgensen

Nobody said:
I don't know whether they support a 64-bit "int"

I believe they do.

On a thread-related note:

I was reading the unaligned-memory-access.txt file that comes with the
kernel source, and found out that GCC will protect against unaligned
memory accesses even when using __attribute__((packed)) (presumably by
generating a small pile of code to do it when necessary):

Another point worth mentioning is the use of __attribute__((packed))
on a structure type. This GCC-specific attribute tells the compiler
never to insert any padding within structures, useful when you want
to use a C struct to represent some data that comes in a fixed
arrangement 'off the wire'.

You might be inclined to believe that usage of this attribute can
easily lead to unaligned accesses when accessing fields that do not
satisfy architectural alignment requirements. However, again, the
compiler is aware of the alignment constraints and will generate
extra instructions to perform the memory access in a way that does
not cause unaligned access. Of course, the extra instructions
obviously cause a loss in performance compared to the non-packed
case, so the packed attribute should only be used when avoiding
structure padding is of importance.

I wonder if this is common behavior in compilers that allow you to
specify packed structures.

-Beej
 
P

Phil Carmody

James Kuyper said:
Phil said:
That can be the case only of the 80-bit floating point values are
padded to at least 96 or 128 bits, where the padding is actually
part of the object. C arrays cannot have gaps between elements.

As someone who uses 80-bit floats a lot, this is one thing that
narks me. It's a clear weakness in the C standard if it has to force
the implementation to lie about the size of an object when
I use sizeof, by telling me the size of the tile in which it fits
instead.

I'd like struct { long double f; char c[2]; } to fit in 12 bytes on
an x86, because in reality it does.

In other words, you don't mind if if is no longer the case that
sizeof(T[N]) == N*sizeof(T), where T is a type name and N is the
dimension of an array of that type. I suppose you could make an
argument for doing it differently in a new language, but it is of
course way too late to make such a change in C - there's far too much
existing code that relies upon that relationship being true.

Which bit of you didn't think I was expressing a disappointment at
the C language itself? Did you read my post? If so, did you parse
it sensibly? If so, did you understand its semantics? If so, why
do you ask such a stupid question?

Or, as they say, "C - it may be the 2nd worst language in the
universe, but everything else shares first place.".

Phil
 
K

Keith Thompson

Beej Jorgensen said:
I believe they do.

On a thread-related note:

I was reading the unaligned-memory-access.txt file that comes with the
kernel source, and found out that GCC will protect against unaligned
memory accesses even when using __attribute__((packed)) (presumably by
generating a small pile of code to do it when necessary):

Another point worth mentioning is the use of __attribute__((packed))
on a structure type. This GCC-specific attribute tells the compiler
never to insert any padding within structures, useful when you want
to use a C struct to represent some data that comes in a fixed
arrangement 'off the wire'.

You might be inclined to believe that usage of this attribute can
easily lead to unaligned accesses when accessing fields that do not
satisfy architectural alignment requirements. However, again, the
compiler is aware of the alignment constraints and will generate
extra instructions to perform the memory access in a way that does
not cause unaligned access. Of course, the extra instructions
obviously cause a loss in performance compared to the non-packed
case, so the packed attribute should only be used when avoiding
structure padding is of importance.

I wonder if this is common behavior in compilers that allow you to
specify packed structures.

I certainly hope so!

A feature that allows you to assign a name to a (possibly misaligned)
piece of a structure, but doesn't allow you to refer to that piece by
its name, would be nearly useless. I suppose you could refer to
"sizeof obj.member" and "&obj.member" and manipulate it using
memcpy(), but that's hardly any better than using an array of unsigned
char.
 
B

Beej Jorgensen

Keith Thompson said:
A feature that allows you to assign a name to a (possibly misaligned)
piece of a structure, but doesn't allow you to refer to that piece by
its name, would be nearly useless.

Agreed. For some reason, I figured the compiler might just say, "Sure,
I'll pack that struct, but you'd better know what you're doing when you
try to access any of it."

But I guess that even though one is explicitly asking it to pack the
struct, there is still an implicit request to generate actual
functioning code. :)

-Beej
 
N

Nobody

On a thread-related note:

I was reading the unaligned-memory-access.txt file that comes with the
kernel source, and found out that GCC will protect against unaligned
memory accesses even when using __attribute__((packed))

It would be more accurate to say "*especially* when using ...".

The usual situation for architectures with alignment requirements is to
assume alignment in the absence of evidence to the contrary. E.g. if a
function takes an int* argument, the compiler will assume that it's
aligned unless there's reason to believe otherwise (e.g. ARM's compiler
uses the __packed qualifier to indicate that a pointer isn't guaranteed to
be aligned).

gcc doesn't have an equivalent of __packed. It will only generate the code
for unaligned access for an explicit read of a packed structure. If you
want to do e.g.:

struct foo {
char a;
int b;
} __attribute__((packed));
struct foo foo;

bar(&foo.b);

then bar() has to be written like e.g.:

void bar(const void *p) {
int x;
memcpy(&x, p, sizeof(x));
...
}

If you make the argument an int*, gcc will assume that it's suitably
aligned, and may use an inline memcpy() which only works for aligned
pointers.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,833
Latest member
BettyeMacf

Latest Threads

Top