Accessing structure elements using pointer math - padding worries?

Q

quantumred

Can I use pointer arithmetic on the members of a structure in the
following way? Should I be worried about structure padding? This works
in my debugger but I wonder if I'm bending some rule here.

struct char_struct {
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
};

struct char_struct test = {50,75,100,225};

unsigned char *c;

c = &test;

if (c[2]==100) // this is okay?
printf("c[2] is 100"); // this does work

c++; // this is okay?
printf("*c is 75"); // this does work
 
J

J. J. Farrell

Can I use pointer arithmetic on the members of a structure in the
following way?

Yes, but not quite as you mean.
Should I be worried about structure padding?
Yes.

This works
in my debugger but I wonder if I'm bending some rule here.

struct char_struct {
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
};

struct char_struct test = {50,75,100,225};

unsigned char *c;

c = &test;

if (c[2]==100) // this is okay?

It's OK in the sense that "you can address anything through an unsigned
character pointer", and the index is less that the size of the
structure. It doesn't necessarily pick up member c of the structure
though.
printf("c[2] is 100"); // this does work

By coincidence, depending on the compiler/platform.
c++; // this is okay?

Yes, as long as you stay within the structure or step to just beyond
it.
printf("*c is 75"); // this does work

Again, not guaranteed to be member d.
 
E

EventHelix.com

Can I use pointer arithmetic on the members of a structure in the
following way? Should I be worried about structure padding? This works
in my debugger but I wonder if I'm bending some rule here.

struct char_struct {
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
};

struct char_struct test = {50,75,100,225};

unsigned char *c;

c = &test;

if (c[2]==100) // this is okay?
printf("c[2] is 100"); // this does work

c++; // this is okay?
printf("*c is 75"); // this does work

This type of access is not recommended. In compiler is not adding any
pads so your test program works. This may not work on a platform where
the char's get padded to 16 or 32 bit boundaries.

The following article should help:
http://www.eventhelix.com/RealtimeMantra/ByteAlignmentAndOrdering.htm
 
G

Gordon Burditt

Can I use pointer arithmetic on the members of a structure in the
following way?
No.

Should I be worried about structure padding?
Yes.

This works
in my debugger but I wonder if I'm bending some rule here.

Is blowing to smithereens with C4 considered "bending"?
struct char_struct {
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
};

If you want an array as a structure member, USE an array as a
structure member.
struct char_struct test = {50,75,100,225};

unsigned char *c;

c = &test;

if (c[2]==100) // this is okay? No.
printf("c[2] is 100"); // this does work

On YOUR version of YOUR compiler and perhaps only as long as you
don't add a double as a fifth member of the structure.
c++; // this is okay?

Yes. Consider a single variable as an array of one element. You
are allowed to compute the address of "one past the last element"
but not dereference it.
printf("*c is 75"); // this does work

Ok, printing a constant string is allowed, but if you were planning
on dereferencing c after incrementing it, NO, that's not allowed.

Gordon L. Burditt
 
B

Barry Schwarz

Can I use pointer arithmetic on the members of a structure in the
following way? Should I be worried about structure padding? This works

Yes you should.
in my debugger but I wonder if I'm bending some rule here.

Murphy's Law. If something can go wrong it will, but only at the
worst possible time. Like when your most important customer tries to
compile the code on his system.
struct char_struct {
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
};

struct char_struct test = {50,75,100,225};

unsigned char *c;

c = &test;

if (c[2]==100) // this is okay?
printf("c[2] is 100"); // this does work

c++; // this is okay?
printf("*c is 75"); // this does work


Remove del for email
 
R

Richard Heathfield

(e-mail address removed) said:
Are there any such platforms ?

Yes. For example, consider platforms where CHAR_BIT is 16 or 32.

(And yes, there are such platforms. Digital signal processors typically have
gurt big chars.)
 
S

slebetman

Richard said:
(e-mail address removed) said:


Yes. For example, consider platforms where CHAR_BIT is 16 or 32.

(And yes, there are such platforms. Digital signal processors typically have
gurt big chars.)

DSP are a bit too exotic for some people to consider significant.
They'll say "but, but it works on my PC!!". I always like to point out
that most ARM compilers do pad chars to 32bit boundries. If they still
look confused and don't get it I'll politely point out that XScale is
ARM. If they still don't get it I'll casually mention that XScale is
what most PocketPC run on and that almost 90% of all Windows CE devices
(not to mention Palm and Psion/Symbian) run on ARM.
 
D

Default User

Can I use pointer arithmetic on the members of a structure in the
following way? Should I be worried about structure padding? This works
in my debugger but I wonder if I'm bending some rule here.

struct char_struct {
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
};

struct char_struct test = {50,75,100,225};

unsigned char *c;

c = &test;

if (c[2]==100) // this is okay?
printf("c[2] is 100"); // this does work


If you desire to treat them like an array, why not make them an array
contained in the struct?




Brian
 
Q

quantumred

Thanks for all the helpful and detailed replies. I spent some time with
offsetof and sizeof and with my MSVC compiler (I am compiling as C, not
C++) it seems char padding is always byte aligned to 1 if the structure
contains only chars.

This is true even if I try to bump it up with #pragma pack(16)
If you desire to treat them like an array, why not make them an array
contained in the struct?

I realize I could just use an array. I'm not determined to implement
such code as described in the original post, but I like to be aware of
my options.
 
S

slebetman

quantumred said:
Thanks for all the helpful and detailed replies. I spent some time with
offsetof and sizeof and with my MSVC compiler (I am compiling as C, not
C++) it seems char padding is always byte aligned to 1 if the structure
contains only chars.

This is true even if I try to bump it up with #pragma pack(16)

Try compiling it for WinCE target on an ARM target. Memory on the x86
platform are byte aligned. But not all CPUs are byte aligned and not
all popular OSes run on x86. Now with .Net being mainly a bytecode
interpreter Microsoft may in the future be free to re-align their
strategy and use a different family of processors (like uh.. I don't
know, PowerPC maybe? like on the new Xbox?).

Linux already run on a variety of CPUs where sloppy code have caused
byte-alignment and endianness problems. Today almost all of the most
popular open source software have been cleaned up thanks in no small
part to people who were determined to port them to those exotic (and
some, like ARM, common) CPUs. Don't repeat the mistakes of those who've
gone through this before.

The lesson is to stick to the C standard and listed to the advice of
seasoned C gurus. Don't believe everything your compiler says is OK.
Remember that the C standard was written in part to make it easy to
implement optimising compilers. Compilers may seem to implement such
extra "features" like byte-wise alignment of structs but they are in
fact just a characteristic of your underlying machine - not really a
feature of C itself.
 
J

J. J. Farrell

quantumred said:
Thanks for all the helpful and detailed replies. I spent some time with
offsetof and sizeof and with my MSVC compiler (I am compiling as C, not
C++) it seems char padding is always byte aligned to 1 if the structure
contains only chars.

This is true even if I try to bump it up with #pragma pack(16)

You can always experiment to discover precisely what this one compiler
does in precisely the mode you're invoking it. But why bother? Do you
want to have to go through that every time someone upgrades the
compiler? Or changes the flags they pass to the comiler? Or uses a
different compiler? Or targets a different system?

Why not just write it in correct C so you're guaranteed it will work
with any options and any C compiler on any system?
 
M

Michael Wojcik

DSP are a bit too exotic for some people to consider significant.

Much as hydrogen is too exotic for some chemists to consider it
significant.

Perhaps the problem is that some programmers have a very poor
understanding of their industry. I'm not sure we should encourage
that by seeking examples they can understand without broadening their
view.

Dump 'em in the crucible, I say. Either they will be refined or
they'll be skimmed off with the rest of the dross.
 
K

Kenneth Brody

Michael said:
Much as hydrogen is too exotic for some chemists to consider it
significant.

Perhaps the problem is that some programmers have a very poor
understanding of their industry. I'm not sure we should encourage
that by seeking examples they can understand without broadening their
view.

On the other hand, many of us require that out programs do more
than can be done with "100% Standard C". Of course, I realize
that if I were to have a question regarding record locking, the
ability to set a terminal into raw mode, etc. etc. etc., I would
ask someplace else.
Dump 'em in the crucible, I say. Either they will be refined or
they'll be skimmed off with the rest of the dross.


--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
M

Michael Wojcik

On the other hand, many of us require that out programs do more
than can be done with "100% Standard C".

I believe that's true. Certainly most of my code must do things
that are not covered by the standard. I don't see how that
contradicts anything I wrote above, however, in which I was merely
arguing against coddling the "all the world's a PC" mentality.
 
S

Stephen Sprunk

Kenneth Brody said:
On the other hand, many of us require that out programs do more
than can be done with "100% Standard C". Of course, I realize
that if I were to have a question regarding record locking, the
ability to set a terminal into raw mode, etc. etc. etc., I would
ask someplace else.

The goal is not to pretend nothing exists outside the C standard, but to
point out what is and isn't in the standard so people _know_ when they're
writing unportable code.

I doubt many programmers have ever written a portable, non-trivial program.
Unportable stuff pays the bills -- but writing gratuitously unportable code
makes your job harder when the inevitable "first port" comes along for any
successful product. Even if you live in POSIX land and never leave, it's
important to know what's part of POSIX and what _that_ doesn't define.

S
 

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,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top