Memory layout question

A

achrist

Here's a program:


#include <stdio.h>
int main(int argc, char **argv)
{
double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};
typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;
typedef a_type *a_type_ptr;
a_type_ptr s_ptr;
s_ptr = (a_type_ptr) an_array;
printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
s_ptr -> v0,
s_ptr -> v1,
s_ptr -> v2,
s_ptr -> v3,
s_ptr -> v4 );
}

Using a recent gcc, this prints out the elements of the array
correctly, i.e.

0.00000 1.00000 2.00000 3.00000 4.00000

For what versions (if any) of standard C is this kluge required to
work? (same alignment and offsets for array items and struct members of
the same type).

TIA


Al
 
J

Jack Klein

Here's a program:


#include <stdio.h>
int main(int argc, char **argv)
{
double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};
typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;
typedef a_type *a_type_ptr;
a_type_ptr s_ptr;
s_ptr = (a_type_ptr) an_array;
printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
s_ptr -> v0,
s_ptr -> v1,
s_ptr -> v2,
s_ptr -> v3,
s_ptr -> v4 );
}

Using a recent gcc, this prints out the elements of the array
correctly, i.e.

0.00000 1.00000 2.00000 3.00000 4.00000

For what versions (if any) of standard C is this kluge required to
work? (same alignment and offsets for array items and struct members of
the same type).

TIA


Al

"required to work"? Absolutely none.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
D

Derk Gwen

(e-mail address removed) wrote:
# Here's a program:
#
#
# #include <stdio.h>
# int main(int argc, char **argv)
# {
# double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};
# typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;
# typedef a_type *a_type_ptr;
# a_type_ptr s_ptr;
# s_ptr = (a_type_ptr) an_array;
# printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
# s_ptr -> v0,
# s_ptr -> v1,
# s_ptr -> v2,
# s_ptr -> v3,
# s_ptr -> v4 );
# }
#
# Using a recent gcc, this prints out the elements of the array
# correctly, i.e.
#
# 0.00000 1.00000 2.00000 3.00000 4.00000
#
# For what versions (if any) of standard C is this kluge required to
# work? (same alignment and offsets for array items and struct members of
# the same type).

Potentially, every single one. The only safe standard way is to pack and
unpack the struct element by element. If you don't want to do that, you
can restrict your concern to just those machines this works on (practically
all of them) and include a dynamic test in the code start up to verify
your assumption.
 
T

Thomas Matthews

Here's a program:


#include <stdio.h>
int main(int argc, char **argv)
{
double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};
typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;
typedef a_type *a_type_ptr;
a_type_ptr s_ptr;
s_ptr = (a_type_ptr) an_array;
printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
s_ptr -> v0,
s_ptr -> v1,
s_ptr -> v2,
s_ptr -> v3,
s_ptr -> v4 );
}

Using a recent gcc, this prints out the elements of the array
correctly, i.e.

0.00000 1.00000 2.00000 3.00000 4.00000

For what versions (if any) of standard C is this kluge required to
work? (same alignment and offsets for array items and struct members of
the same type).

TIA


Al

In summary, you are trying to access a structure:
struct MyStruct
{
double v0;
double v1;
/* ... */
double v4;
};
as an array.

There is what I call the Structure Size Rule for C and C++:
"The size of a structure _may_ not be equal to the sum of
the size of its members."
This rule comes about because a compiler is allowed to
add "padding" elements after each member or field of a
structure. The compiler may want to add the padding to
make the fields easier or more convenient for the processor
to access.

Let us say we have a processor that likes to retrieve
32 bit quantities, known as a fetch. Let us also say
that the processor has an 8-bit char, 16-bit short int
and a 32-bit int (unsigned have the same sizes). When
the processor needs to fetch any of these quantities,
it fetches 32 bits at a time and discards the rest.

Given the following structure:
struct Example
{
char a;
short int b;
int c;
};

The member 'a' is 8-bits wide. The processor wants to
fetch 32 bits. Without any padding the process will
fetch 8 bits of 'a', 16 more bits of 'b' and finally
8 bits of 'c'. It will discard the unused bits, which
in this case, is no problem.

The member 'b' is 16-bits wide, but not at the first
fetch. The processor must fetch from the location
of the first member, remove the extraneous bits
then shift the remaining 16 bits to the correct
position. If we added 24 bits (32 bits - 8 bits
of char) of padding between 'a' and 'b', then the
fetching of 'b' would have no extraneous bits and
no shifting to take place -- more efficient.

The process of adding padding space is called
"alignment". Alignment allows processors to fetch
data more efficiently. However, adding padding
changes the size and layout of a structure. One
cannot map the members of a structure to a real
world structure because of the Structure Size Rule.

Packed Structures
-----------------
Some compilers have #pragmas that allow "packing"
of structures. The term "packing" referes to the
elimination of padding after members. This is not
a standard C facility. Also, many compilers may
allow packed structures but have problems accessing
data from them correctly.

Converting to Structures
------------------------
The best process for handling real world data structures
is to treat them as a sequence of "bytes" and extract
and build the data yourself. This technique also allows
one to handle Endianism (the ordering of "bytes" for
multi-byte units). Once the structure is filled,
it can then be accessed without any worries. The
opposite should be followed when creating a sequence
of bytes from a structure.


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
B

Barry Schwarz

Here's a program:


#include <stdio.h>
int main(int argc, char **argv)
{
double an_array[] = {0.0, 1.0, 2.0, 3.0, 4.0};

The elements of the array are guaranteed to be contiguous in memory
(no gap between the end of an_array[0] and the beginning of
an_array[1], etc).
typedef struct a_struct {double v0, v1, v2,v3, v4;} a_type;

There is no guarantee that the members of the structure will be
contiguous (there may be padding between v0 and v1, etc).
typedef a_type *a_type_ptr;
a_type_ptr s_ptr;
s_ptr = (a_type_ptr) an_array;

There is no guarantee that the alignment of an_array will satisfy the
alignment requirement of the structure.
printf( "%8.5f %8.5f %8.5f %8.5f %8.5f\n",
s_ptr -> v0,
s_ptr -> v1,
s_ptr -> v2,
s_ptr -> v3,
s_ptr -> v4 );
}

Using a recent gcc, this prints out the elements of the array
correctly, i.e.

0.00000 1.00000 2.00000 3.00000 4.00000

Pure luck (good or bad depending on your viewpoint).
For what versions (if any) of standard C is this kluge required to
work? (same alignment and offsets for array items and struct members of
the same type).

There are only two standards (C89 and C99). The comments above apply
to both. The answer to your question is none.


<<Remove the del for email>>
 
T

those who know me have no need of my name

in comp.lang.c i read:
(e-mail address removed) wrote:
# For what versions (if any) of standard C is this kluge required to
# work? (same alignment and offsets for array items and struct members of
# the same type).

Potentially, every single one.

also, potentially none.
The only safe standard way is to pack and unpack the struct element by
element. If you don't want to do that, you can restrict your concern to
just those machines this works on (practically all of them) and include a
dynamic test in the code start up to verify your assumption.

and depend on the results of undefined behavior? no thanks.
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,169
Latest member
ArturoOlne
Top