union with packed struct

C

ccwork

Hi all,
Here is a sample code segment:
....
typedef PACKED struct
{
union
{
PACKED struct
{
char red:1;
char green:1;
char blue:1;
} color_bit;
char color;
} color_u;
} color_t;

color_t color;
....
My question is: which bit in "color.color_u.color" reflect
"color.color_u.color_bit.red", "color.color_u.color_bit.green" and
"color.color_u.color_bit.blue"? Is this well defined?
In other words, if I set "color.color_u.color_bit.red" as 0,
"color.color_u.color_bit.green" as 0 and "color.color_u.color_bit.blue"
as 1, What will be "color.color_u.color"? is it 0x04?
 
J

Jack Klein

Hi all,
Here is a sample code segment:

Actually, it is an illegal code segment.
...
typedef PACKED struct
{
union
{
PACKED struct

In the first place, the typedef is not complete so you can't use.
Secondly, you appear to be trying to define a type that contains an
instance of itself as a member.
{
char red:1;
char green:1;
char blue:1;
} color_bit;

Also note that prior to the 1999 version of the C standard, the only
allowed types for bit-field members is signed or unsigned int. C99
allows, but does not require, implementations to accept other integer
types.
char color;
} color_u;
} color_t;

color_t color;

Next time try posting code that will actually pass through a C
compiler without error.
...
My question is: which bit in "color.color_u.color" reflect
"color.color_u.color_bit.red", "color.color_u.color_bit.green" and
"color.color_u.color_bit.blue"? Is this well defined?
In other words, if I set "color.color_u.color_bit.red" as 0,
"color.color_u.color_bit.green" as 0 and "color.color_u.color_bit.blue"
as 1, What will be "color.color_u.color"? is it 0x04?

Almost everything about bit-fields is implementation defined. It is
entirely up to your compiler as to how it places the bits in the type
it uses for storage. Check your compiler's documentation.
 
E

Eric Sosman

ccwork said:
Hi all,
Here is a sample code segment:
...
typedef PACKED struct

What is `PACKED'? It isn't a C construct -- it looks
like it's probably a #defined macro that expands to (one
would guess) some kind of implementation-specific extension
to C like `__attribute__((packed))'. If so, you'll need to
consult your implementation's documentation to find out
what's going on, because it isn't C.

Well, it *could* be C, if `PACKED' expands to something
like `volatile' or `const' or nothing at all. In what
follows, I'll assume that's the case.
{
union
{
PACKED struct
{
char red:1;
char green:1;
char blue:1;
} color_bit;
char color;
} color_u;
} color_t;

color_t color;
...
My question is: which bit in "color.color_u.color" reflect
"color.color_u.color_bit.red", "color.color_u.color_bit.green" and
"color.color_u.color_bit.blue"? Is this well defined?

Not by the C language. The compiler has great freedom
in how it chooses to arrange bit-fields within a struct.
Different compilers will arrange things differently.
In other words, if I set "color.color_u.color_bit.red" as 0,
"color.color_u.color_bit.green" as 0 and "color.color_u.color_bit.blue"
as 1, What will be "color.color_u.color"? is it 0x04?

Not necessarily. In fact, it's not guaranteed that
`color.color_u.color' will have a valid value at all: unions
are frequently (ab)used for this sort of type punning, but
the language doesn't promise that anything reasonable will
happen if you try it.

If you want to represent a color as three bits in a
`char', you're better off using bitwise operators with
pre-#defined (or enum-erated) masks:

typedef unsigned char color_t;
#define COLOR_RED 1
#define COLOR_GREEN 2
#define COLOR_BLUE 4
#define COLOR_YELLOW (COLOR_GREEN | COLOR_RED)
...
 
C

ccwork

Hi,
How about assign "color.color_u.color_bit.red" to something other
than 0 and 1? Say color.color_u.color_bit.red=20. What will happen?
How about assign color.color_u.color_bit.red=(some expression) &&
(another expression)?

Actually all these are code from a senior engineer and I am helping
him...
 
D

DHOLLINGSWORTH2

packed structures means to put the next one emmediately following the first
one, instead of on 64 bit boundaries.

You should note that structs, unions, and classess are designed to help the
programmer not the computer. You will find that aligning your data within
each Struct to 64 bit boundaries allows you a few more machine cycles than
all the tidbitley wringing done to code to "optimize" it.

Keep in mind that a struct is just an int[], with mapping handles for the
"Programmer".

I hope you gain something from this.

ccwork said:
Hi,
How about assign "color.color_u.color_bit.red" to something other
than 0 and 1? Say color.color_u.color_bit.red=20. What will happen?
How about assign color.color_u.color_bit.red=(some expression) &&
(another expression)?

Actually all these are code from a senior engineer and I am helping
him...
 
M

Mark McIntyre

packed structures means to put the next one emmediately following the first
one, instead of on 64 bit boundaries.

Note that there's no requirement from the C Standard for data to be aligned
on 64-bit boundaries. This woudn't make much sense on a 36-bit machine.
Keep in mind that a struct is just an int[], with mapping handles for the
"Programmer".

Nonsense.
 
C

ccwork

Mark said:
packed structures means to put the next one emmediately following the first
one, instead of on 64 bit boundaries.

Note that there's no requirement from the C Standard for data to be aligned
on 64-bit boundaries. This woudn't make much sense on a 36-bit machine.
Keep in mind that a struct is just an int[], with mapping handles for the
"Programmer".

Nonsense.

Can you elaborate this further?
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption
=----
 
D

DHOLLINGSWORTH2

I'm kind of wondering what you think is nonsense about it.
While it is true that the actual boundary, and size is dependent on the HW.
The idea is still the same.

And I'm afraid that what you call "nonsense", is actually refered to as a
FLAT MEMORY MODEL.

That means that 20 bytes is 20 bytes. it means that all of the memory on
your system is in the form of :
int[MEMORY_SIZE]
With int, being the size of the register Accessing memory, The actual # of
bits read in. I dont how else to describe it to you.

But
struct _tegname{
char some_of_ this_nonsense;
int * Some_of_that_nonsense;
short Some_mmore_Nonsense;
....
}, NONSENSE;

is stored in that FLAT MEMORY MODEL.
ie: int[];



ccwork said:
Mark said:
packed structures means to put the next one emmediately following the first
one, instead of on 64 bit boundaries.

Note that there's no requirement from the C Standard for data to be aligned
on 64-bit boundaries. This woudn't make much sense on a 36-bit machine.
Keep in mind that a struct is just an int[], with mapping handles for the
"Programmer".

Nonsense.

Can you elaborate this further?
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption
=----
 
W

Walter Roberson

:And I'm afraid that what you call "nonsense", is actually refered to as a
:FLAT MEMORY MODEL.

What you are calling a "flat memory model" is one -particular- flat memory
model, which does not hold true on all flat memory systems.


:That means that 20 bytes is 20 bytes. it means that all of the memory on
:your system is in the form of :
:int[MEMORY_SIZE]
:With int, being the size of the register Accessing memory, The actual # of
:bits read in. I dont how else to describe it to you.

So then, how do you explain the Honeywell L66 architecture, which
could store 6 characters per word, 36 bits per word, and had 9 bit bytes?

You are assuming that all memory is alignable in "int" chunks. That
isn't true on all architectures: on some architectures (e.g., the L66),
you need to use different instructions to get at different data types.
Some architectures store 80 bits per double, and can put doubles
back to back, and yet for normal operations require that int be aligned
on 32 bit boundaries.

:But
:struct _tegname{
: char some_of_ this_nonsense;
: int * Some_of_that_nonsense;
: short Some_mmore_Nonsense;
:...
:}, NONSENSE;

:is stored in that FLAT MEMORY MODEL.
:ie: int[];

Some architectures have pointers which are not the size of int (or
long) and which can be aligned on different boundaries than int.

For example, the representation of two of the above in memory
could have this byte layout:

0 : some_of_this_nonsense character 0 = int 0 byte 0
1 : unused padding = int 0 byte 1
2 : Some_of_that_nonsense byte 0 = int 0 byte 2
3 : Some_of_that_nonsense byte 1 = int 0 byte 3
4 : Some_of_that_nonsense byte 2 = int 1 byte 0
5 : Some_of_that_nonsense byte 3 = int 1 byte 1
6 : Some_of_that_nonsense byte 4 = int 1 byte 2
7 : Some_of_that_nonsense byte 5 = int 1 byte 3
8 : Some_mmore_Nonsense byte 0 = int 2 byte 0
9 : Some_mmore_Nonsense byte 1 = int 2 byte 1

A : some_of_this_nonsense2 character 0 = int 2 byte 2
B : unused padding = int 2 byte 3
C : Some_of_that_nonsense2 byte 0 = int 3 byte 0
D : Some_of_that_nonsense2 byte 1 = int 3 byte 1
E : Some_of_that_nonsense2 byte 2 = int 3 byte 2
F : Some_of_that_nonsense2 byte 3 = int 3 byte 3
10: Some_of_that_nonsense2 byte 4 = int 4 byte 0
11: Some_of_that_nonsense2 byte 5 = int 4 byte 1
12: Some_mmore_Nonsense2 byte 0 = int 4 byte 2
13: Some_mmore_Nonsense2 byte 1 = int 4 byte 3

The architecture could have instructions able to load characters
from arbitrary bytes, to load 6 byte pointers from 2 byte boundaries,
to load 2 byte shorts from 2 byte boundaries, and yet might not
have any instruction to load int from 2 byte boundaries, only
from 4 byte boundaries. In such an architecture, the structure
is not representable as an array of int -- not without having
the array of int include data that belongs to another object!


If you examine the alignment rules of the Standard, you will
see that basically there -aren't- any alignment rules in
the Standard, other than that malloc() shall return a pointer
which satisfies the alignment rules for all primitive data types.
sizeof(short) <= sizeof(int) <= sizeof(long)
but that doesn't tell us anything about how short, int, or long
must be aligned in memory. Converting a short into an int
is not necessarily just a matter of moving 0 into the int
and then MOV.S the short into the "bottom short" of the int:
it is perfectly acceptable for the achitecture to use
a complete different set of registers for working with
shorts and int, with an explicit "extend short to int"
instruction instruction. (And yes, I really have seen
architectures with "extend short to int" instructions --
and no, they weren't synonyms for "sign extend short to
int".)
 
D

DHOLLINGSWORTH2

I'm sorry, when you show me a computer with contiguous ram, that has more
than one memory location for any one given address then you'll have an
argument.

Call it what you want :
somesize[];
MyCompsRegWidth[];
MyRamsWordSize[];

There is a level of comprehension and understanding that I wrongfully
assumed that every english typing programmer had.

and yes : int[], char[], word[], WhatHaveYa[];

is all the same in HW.

STRUCTS are there for the programmer, not the computer!



Walter Roberson said:
:And I'm afraid that what you call "nonsense", is actually refered to as a
:FLAT MEMORY MODEL.

What you are calling a "flat memory model" is one -particular- flat memory
model, which does not hold true on all flat memory systems.


:That means that 20 bytes is 20 bytes. it means that all of the memory on
:your system is in the form of :
:int[MEMORY_SIZE]
:With int, being the size of the register Accessing memory, The actual #
of
:bits read in. I dont how else to describe it to you.

So then, how do you explain the Honeywell L66 architecture, which
could store 6 characters per word, 36 bits per word, and had 9 bit bytes?

You are assuming that all memory is alignable in "int" chunks. That
isn't true on all architectures: on some architectures (e.g., the L66),
you need to use different instructions to get at different data types.
Some architectures store 80 bits per double, and can put doubles
back to back, and yet for normal operations require that int be aligned
on 32 bit boundaries.

:But
:struct _tegname{
: char some_of_ this_nonsense;
: int * Some_of_that_nonsense;
: short Some_mmore_Nonsense;
:...
:}, NONSENSE;

:is stored in that FLAT MEMORY MODEL.
:ie: int[];

Some architectures have pointers which are not the size of int (or
long) and which can be aligned on different boundaries than int.

For example, the representation of two of the above in memory
could have this byte layout:

0 : some_of_this_nonsense character 0 = int 0 byte 0
1 : unused padding = int 0 byte 1
2 : Some_of_that_nonsense byte 0 = int 0 byte 2
3 : Some_of_that_nonsense byte 1 = int 0 byte 3
4 : Some_of_that_nonsense byte 2 = int 1 byte 0
5 : Some_of_that_nonsense byte 3 = int 1 byte 1
6 : Some_of_that_nonsense byte 4 = int 1 byte 2
7 : Some_of_that_nonsense byte 5 = int 1 byte 3
8 : Some_mmore_Nonsense byte 0 = int 2 byte 0
9 : Some_mmore_Nonsense byte 1 = int 2 byte 1

A : some_of_this_nonsense2 character 0 = int 2 byte 2
B : unused padding = int 2 byte 3
C : Some_of_that_nonsense2 byte 0 = int 3 byte 0
D : Some_of_that_nonsense2 byte 1 = int 3 byte 1
E : Some_of_that_nonsense2 byte 2 = int 3 byte 2
F : Some_of_that_nonsense2 byte 3 = int 3 byte 3
10: Some_of_that_nonsense2 byte 4 = int 4 byte 0
11: Some_of_that_nonsense2 byte 5 = int 4 byte 1
12: Some_mmore_Nonsense2 byte 0 = int 4 byte 2
13: Some_mmore_Nonsense2 byte 1 = int 4 byte 3

The architecture could have instructions able to load characters
from arbitrary bytes, to load 6 byte pointers from 2 byte boundaries,
to load 2 byte shorts from 2 byte boundaries, and yet might not
have any instruction to load int from 2 byte boundaries, only
from 4 byte boundaries. In such an architecture, the structure
is not representable as an array of int -- not without having
the array of int include data that belongs to another object!


If you examine the alignment rules of the Standard, you will
see that basically there -aren't- any alignment rules in
the Standard, other than that malloc() shall return a pointer
which satisfies the alignment rules for all primitive data types.
sizeof(short) <= sizeof(int) <= sizeof(long)
but that doesn't tell us anything about how short, int, or long
must be aligned in memory. Converting a short into an int
is not necessarily just a matter of moving 0 into the int
and then MOV.S the short into the "bottom short" of the int:
it is perfectly acceptable for the achitecture to use
a complete different set of registers for working with
shorts and int, with an explicit "extend short to int"
instruction instruction. (And yes, I really have seen
architectures with "extend short to int" instructions --
and no, they weren't synonyms for "sign extend short to
int".)
 
W

Walter Roberson

:I'm sorry, when you show me a computer with contiguous ram, that has more
:than one memory location for any one given address then you'll have an
:argument.

There are several systems around for which the smallest addressible
unit is the "word", and there are special instructions necessary
to extract characters within words. For some of those, a character
can start at an arbitrary bit position within the word!

On bitslice architectures, bit-wise packing of structures is
possible -- e.g., if you had

typedef struct { unsigned int i:3, char c, int j } s3cj;
s3cj A[2];

then the compiler might choose to lay A out in memory as (bitwise)

iiiccccccccjjjjjjjjjjjjjjjjjjjjj
jjjjjjjjjjjiiiccccccccjjjjjjjjj
jjjjjjjjjjjjjjjjjjjjjjj
0123456789ABCDEF0123456789ABCDEF

Clearly on such an architecture, the offset to j is not
a multiple of a byte/word/int/long .

:and yes : int[], char[], word[], WhatHaveYa[];
:is all the same in HW.

Wrong. There has perhaps been an equivilence on all the architectures
you have worked on, but you have to remember that C is defined in such
a way as to be implimentable on oddities such as 1's compliment
machines and embedded microprocessors.

It isn't uncommon on RISC machines for the actual memory size read or
written for each access to main memory to be fairly large -- an entire
"cache line" at a time, where a cache might be (e.g.) 64 bytes. On
such systems, the smallest individually addressible unit may be the 32
bit or 64 bit long, with there being extra instructions needed to
access smaller units.

As far as the C standard is concerned, there is no problem if, instead
of the memory being a stream of individually addressible bytes, there
are addressing modes that take a base address and an index and access
or store at the appropriate location; e.g., MOV.S A3(D6),D0 could
perform an index operation into memory, taking the D6'th short from the
begining of A3, even though that might not fall onto a directly
addressible boundary.

If you re-examine what you are allowed to do with pointers, you will
find that you are not allowed to compare pointers to different
objects [even of the same type], and that casting a pointer to
anything other than a "compatible" type is not certain to be
meaningful. Converting a pointer to (void *) and back again
is constrained to compare equal to the original, but it is
legal for different pointer types to be different sizes
and to hold different internal information.
 
D

DHOLLINGSWORTH2

You can slice it by the bit, you can slice it by GiG.

There is still only one address per Location!

I have used microproccessors with RISC, with nonrisc, even some with a
PRogrammable micro code.

And on every Computer, microproccessor, digital circuit, there is still only
one location for the specified address, I dont care how big or small a chunk
you look at. Or on what HW you look at.

The computer will not change it's abilities to read what the Memory bus can
put out between members in a struct.
There is NO physical conection.

You act like your bits can't possibly be what the HW was designed to
manipulate.

Why would you build a 32 bit data bus and say that reading 4 chunks of 8
bits each were any faster than reading the whole 32.
would reading 32 chunks of 1 bit, be even faster?

IT doesn't matter, in memory, the BITS are stored in contiguous groups.

For example the 486 uses 32 bit registers, the actual indexing is done 8
bits per address. However reading 4 chars is slower than 1 dword.
Becuase you read 32 bits for each char read. FACT!

even on your micropro with bitslicing architecture, lets say you have 16
bits of data bus, but you only want to use 4 bits. OK you can, ITs still in
the middle of one huge array of integers. FACT! It's still contiguous.

And every time you access those 4 bits they are in the same Physical
location as before.

I think you may have confused what I was saying with how I was saying it.

Do you think we should optimize code that only utilized 1/8 of the register,
or 1/4 of the data bus, whats the point.
You have to get the code to run twice as fast to make up for only using 1/2
the registers, 1/2 data bus, etc.
Thats always going to be true. And that is my point.



Walter Roberson said:
:I'm sorry, when you show me a computer with contiguous ram, that has more
:than one memory location for any one given address then you'll have an
:argument.

There are several systems around for which the smallest addressible
unit is the "word", and there are special instructions necessary
to extract characters within words. For some of those, a character
can start at an arbitrary bit position within the word!

On bitslice architectures, bit-wise packing of structures is
possible -- e.g., if you had

typedef struct { unsigned int i:3, char c, int j } s3cj;
s3cj A[2];

then the compiler might choose to lay A out in memory as (bitwise)

iiiccccccccjjjjjjjjjjjjjjjjjjjjj
jjjjjjjjjjjiiiccccccccjjjjjjjjj
jjjjjjjjjjjjjjjjjjjjjjj
0123456789ABCDEF0123456789ABCDEF

Clearly on such an architecture, the offset to j is not
a multiple of a byte/word/int/long .

:and yes : int[], char[], word[], WhatHaveYa[];
:is all the same in HW.

Wrong. There has perhaps been an equivilence on all the architectures
you have worked on, but you have to remember that C is defined in such
a way as to be implimentable on oddities such as 1's compliment
machines and embedded microprocessors.

It isn't uncommon on RISC machines for the actual memory size read or
written for each access to main memory to be fairly large -- an entire
"cache line" at a time, where a cache might be (e.g.) 64 bytes. On
such systems, the smallest individually addressible unit may be the 32
bit or 64 bit long, with there being extra instructions needed to
access smaller units.

As far as the C standard is concerned, there is no problem if, instead
of the memory being a stream of individually addressible bytes, there
are addressing modes that take a base address and an index and access
or store at the appropriate location; e.g., MOV.S A3(D6),D0 could
perform an index operation into memory, taking the D6'th short from the
begining of A3, even though that might not fall onto a directly
addressible boundary.

If you re-examine what you are allowed to do with pointers, you will
find that you are not allowed to compare pointers to different
objects [even of the same type], and that casting a pointer to
anything other than a "compatible" type is not certain to be
meaningful. Converting a pointer to (void *) and back again
is constrained to compare equal to the original, but it is
legal for different pointer types to be different sizes
and to hold different internal information.
 
C

ccwork

Hi,
for the struct:

struct S
{
char a;
char b;
char c;
} s;

According to your meaning that struct is int [], this mean:
1) ((int *)&s)[0] = s.a
2) ((int *)&s)[1] = s.b
3) ((int *)&s)[2] = s.c
Most likely this is wrong if sizeof(char) < sizeof(int). Walter
Roberson gave a very good example of bitslice architecture that
addressess of individual member of a struct can be ANY, not necessarily
multiple of char/short/int/long.
You can slice it by the bit, you can slice it by GiG.

There is still only one address per Location!

I have used microproccessors with RISC, with nonrisc, even some with a
PRogrammable micro code.

And on every Computer, microproccessor, digital circuit, there is still only
one location for the specified address, I dont care how big or small a chunk
you look at. Or on what HW you look at.

The computer will not change it's abilities to read what the Memory bus can
put out between members in a struct.
There is NO physical conection.

You act like your bits can't possibly be what the HW was designed to
manipulate.

Why would you build a 32 bit data bus and say that reading 4 chunks of 8
bits each were any faster than reading the whole 32.
would reading 32 chunks of 1 bit, be even faster?

IT doesn't matter, in memory, the BITS are stored in contiguous groups.

For example the 486 uses 32 bit registers, the actual indexing is done 8
bits per address. However reading 4 chars is slower than 1 dword.
Becuase you read 32 bits for each char read. FACT!

even on your micropro with bitslicing architecture, lets say you have 16
bits of data bus, but you only want to use 4 bits. OK you can, ITs still in
the middle of one huge array of integers. FACT! It's still contiguous.

And every time you access those 4 bits they are in the same Physical
location as before.

I think you may have confused what I was saying with how I was saying it.

Do you think we should optimize code that only utilized 1/8 of the register,
or 1/4 of the data bus, whats the point.
You have to get the code to run twice as fast to make up for only using 1/2
the registers, 1/2 data bus, etc.
Thats always going to be true. And that is my point.



Walter Roberson said:
:I'm sorry, when you show me a computer with contiguous ram, that has more
:than one memory location for any one given address then you'll have an
:argument.

There are several systems around for which the smallest addressible
unit is the "word", and there are special instructions necessary
to extract characters within words. For some of those, a character
can start at an arbitrary bit position within the word!

On bitslice architectures, bit-wise packing of structures is
possible -- e.g., if you had

typedef struct { unsigned int i:3, char c, int j } s3cj;
s3cj A[2];

then the compiler might choose to lay A out in memory as (bitwise)

iiiccccccccjjjjjjjjjjjjjjjjjjjjj
jjjjjjjjjjjiiiccccccccjjjjjjjjj
jjjjjjjjjjjjjjjjjjjjjjj
0123456789ABCDEF0123456789ABCDEF

Clearly on such an architecture, the offset to j is not
a multiple of a byte/word/int/long .

:and yes : int[], char[], word[], WhatHaveYa[];
:is all the same in HW.

Wrong. There has perhaps been an equivilence on all the architectures
you have worked on, but you have to remember that C is defined in such
a way as to be implimentable on oddities such as 1's compliment
machines and embedded microprocessors.

It isn't uncommon on RISC machines for the actual memory size read or
written for each access to main memory to be fairly large -- an entire
"cache line" at a time, where a cache might be (e.g.) 64 bytes. On
such systems, the smallest individually addressible unit may be the 32
bit or 64 bit long, with there being extra instructions needed to
access smaller units.

As far as the C standard is concerned, there is no problem if, instead
of the memory being a stream of individually addressible bytes, there
are addressing modes that take a base address and an index and access
or store at the appropriate location; e.g., MOV.S A3(D6),D0 could
perform an index operation into memory, taking the D6'th short from the
begining of A3, even though that might not fall onto a directly
addressible boundary.

If you re-examine what you are allowed to do with pointers, you will
find that you are not allowed to compare pointers to different
objects [even of the same type], and that casting a pointer to
anything other than a "compatible" type is not certain to be
meaningful. Converting a pointer to (void *) and back again
is constrained to compare equal to the original, but it is
legal for different pointer types to be different sizes
and to hold different internal information.
Dave Smey
 
M

Mark F. Haigh

Walter said:
DHOLLINGSWORTH2 <[email protected]> wrote:

If you re-examine what you are allowed to do with pointers, you will
find that you are not allowed to compare pointers to different
objects [even of the same type],

Incorrect:

6.5.9 Equality operators

[...]

6 Two pointers compare equal if and only if both are
null pointers, both are pointers to the same object
(including a pointer to an object and a subobject
at its beginning) or function, both are pointers to
one past the last element of the same array object,
or one is a pointer to one past the end of one array
object and the other is a pointer to the start of a
different array object that happens to immediately
follow the first array object in the address space.



Mark F. Haigh
(e-mail address removed)
 
D

DHOLLINGSWORTH2

no,

what I mean is that

char * s ="Some text in ram!";

the text "Some text in ram!" is actually stored in ram.
in contiguous chunks.

you could say char s[]; represents an area in ram at s,

I'M Saying that all of your ram can be looked at like
int []; instead of some char [], some word[]; etc.

When you store the data in a form the Hardware naturally proccessess you are
going to save more clock cycles than you will pull out optimizing your code
by hand.

Simple put, Streamlining your code, does more for you than optimizing. When
you use data structures that are not in anyway equivelant to the native
operation of your HW.

char s[] = "Some text in Ram";

as an int[]; is the same exact pattern in memory;

as a programmer you would have to unpack the integer to get the individual
char values. when you use char []; the packing, and unpacking is done
"behind the scene".

Lets say you have a struct :

struct myStruct {
short x;
short y;
short z;
} coord;

accessing coord.x means you are loading an intire register with int, and
croping it to obtain the short portion.

in effect, incrementing x, y, z means you have loaded at least one of these
twice, once you through it out, and the second time, you through the rest
out.

on a 64 bit machine, Which reads and writes 64 bits at a time, you would
read in each value, 16 bits, once, and get the other 48 bits with it, crop
it ( unpack) , increment it, add the 48 bits back in,( pack it ), then save
it back to ram.

you could read all 3 shorts at once by alligning your structure on a 64 bit
boundary, and inc each one in one clock cycle, and similarly in one write
cycle store all three values back.
or
(this was my original statement)
you can redifine mystruct
struct mystruct {
int x;
int y;
int z,
} coord;

now since the x, y, and z values match the register width, the Databus
width, you don't have to ( unpack) or (pack) anything,

of the three methods here,

the first one really helps the programmer, and saves space, at the expense
of clock cycles,

the second method saves space, and saves clock cycles at the expense of the
programmer,

while the third method uses more space, but huals ass, and takes just as
much time to code as the 1st method.

I'm not going to suggest not using char, You would have to write a sh__ load
of string proccessing code, ( "already been done").
But you can logically order the information, and resize some information to
give you the best of all 3 methods.

I hope this clears up what I was trying to say the first post.

I thought everyone could follow it ok. I was wrong.

IF( I_hurt_anyones_feeling)
{
my_Oppologies();
}
else O_FN_WELL;

Later,

Dan
 
R

Richard Bos

Mark F. Haigh said:
Walter said:
If you re-examine what you are allowed to do with pointers, you will
find that you are not allowed to compare pointers to different
objects [even of the same type],

Incorrect:

6.5.9 Equality operators
6 Two pointers compare equal if and only if

Equal, yes. You're allowed to compare pointers for equality. This is
simply done even in segmented or type-separated memory by noting that
two non-null pointers of different type need never compare equal at all:
they point to different kinds of objects, therefore not to the same
object; they are by definition not null; and if types are separated, an
array of one type never follows an array of another type.
If memory really were a gigantic array of ints, as DHOLLINGSWORTH2 seems
to think, then you would be able to do a lot more. You could, for
example, compare random pointers for order. That may be possible on many
common systems, but the Standard doesn't guarantee it.

Richard
 
D

DHOLLINGSWORTH2

----- Original Message -----
From: "Richard Bos" <[email protected]>
Newsgroups: comp.lang.c
Sent: Wednesday, March 09, 2005 4:01 AM
Subject: Re: union with packed struct

If memory really were a gigantic array of ints, as DHOLLINGSWORTH2 seems
to think, then you would be able to do a lot more. You could, for

if it wern't youd be wondering what a pointer is for. How to clear up the
ambiguity and what not.

if it weren't you would not be able to this:

char * text = "Some bs text to prove a DA point";
char text2[32];

int * pitext = text;
int * pitext2 = text2;

for( int i = 0; i < (32/ sizeof( int)); i++)
{
pitext2 = pitext;
}

// which copies from one string to the next
// by int's instead of by chars
// 4 times faster on 32 bit machine,
// and 8 times faster on a 64 bit machine

MEM is also just an array of bits;
also just an array of bytes;
also just an array of short's;
but where the i86 architecture is concerned
it's most like an array of int's.

I haven't seen a compiler one that shows any difference to that FACT.

common systems, but the Standard doesn't guarantee it.

I'll give you that, my specialty is doing all the Dirty NON-STANDARD work
you think can't get done.
 
M

Mark F. Haigh

DHOLLINGSWORTH2 said:
You can slice it by the bit, you can slice it by GiG.

There is still only one address per Location!

'Address' is not so easily defined. There may be 10,000 processes
running on a box, each with 10,000 different ideas of what exists at
virtual address 0x1234.

Further, a pointer with the integer value of 42 may mean the 42nd byte
of memory, the 42nd word, or the 42,000th quadword. It all depends on
the type of the pointer.

What we are concerned with here is the meaning the C standard gives to
'address', and what is guaranteed, no matter what the platform
involved.
I have used microproccessors with RISC, with nonrisc, even some with a
PRogrammable micro code.

And on every Computer, microproccessor, digital circuit, there is still only
one location for the specified address, I dont care how big or small a chunk
you look at. Or on what HW you look at.

Whoopdee doo. You're talking to people here that deal with and develop
for these systems daily.
The computer will not change it's abilities to read what the Memory bus can
put out between members in a struct.
There is NO physical conection.

You act like your bits can't possibly be what the HW was designed to
manipulate.

Why would you build a 32 bit data bus and say that reading 4 chunks of 8
bits each were any faster than reading the whole 32.
would reading 32 chunks of 1 bit, be even faster?

You clearly don't understand what you're talking about. Who said
anything about a 32 bit data bus? It could be a 1 bit data bus for all
you know.
IT doesn't matter, in memory, the BITS are stored in contiguous groups.

That's not even partially correct. There may be all kinds of holes in
a physical or virtual memory map. The 'next' bit may be on your local
DIMM 0 or in an undisclosed location across the Pacific in Kaz Khyleku
and Dan Pop's underground lair of doom. So no, bits are not always
stored contiguously, be it physically, virtually, or logically.

Additionally, objects themselves can contain 'padding' bits, whose
values are unspecified:

6.2.6.2 Integer types

1 For unsigned integer types other than unsigned char,
the bits of the object representation shall be divided
into two groups: value bits and padding bits (there need
not be any of the latter).
[...]
The values of any padding bits are unspecified.

For example the 486 uses 32 bit registers, the actual indexing is done 8
bits per address. However reading 4 chars is slower than 1 dword.
Becuase you read 32 bits for each char read. FACT!

even on your micropro with bitslicing architecture, lets say you have 16
bits of data bus, but you only want to use 4 bits. OK you can, ITs still in
the middle of one huge array of integers. FACT! It's still contiguous.

And every time you access those 4 bits they are in the same Physical
location as before.

No. Your claims run from the misleading to the blatantly wrong.
I think you may have confused what I was saying with how I was saying it.

Do you think we should optimize code that only utilized 1/8 of the register,
or 1/4 of the data bus, whats the point.
You have to get the code to run twice as fast to make up for only using 1/2
the registers, 1/2 data bus, etc.
Thats always going to be true. And that is my point.

Nothing you have just said will always be true. 'Optimization' itself
is even loosely defined, as it depends on the situation.

Also, please stop top-posting, it's annoying.


Mark F. Haigh
(e-mail address removed)
 
M

Mark F. Haigh

DHOLLINGSWORTH2 said:
----- Original Message -----
From: "Richard Bos" <[email protected]>
Newsgroups: comp.lang.c
Sent: Wednesday, March 09, 2005 4:01 AM
Subject: Re: union with packed struct

If memory really were a gigantic array of ints, as DHOLLINGSWORTH2 seems
to think, then you would be able to do a lot more. You could, for

if it wern't youd be wondering what a pointer is for. How to clear up the
ambiguity and what not.

if it weren't you would not be able to this:

char * text = "Some bs text to prove a DA point";
char text2[32];

int * pitext = text;
int * pitext2 = text2;

for( int i = 0; i < (32/ sizeof( int)); i++)
{
pitext2 = pitext;
}


No. You presume that &text[0] and &text2[0] are aligned properly for
int access. This code could generate an alignment trap on the ARM
processor box here on my desk.

Not to mention that since you're using signed ints to copy the data,
you could inadvertently cause an int to be loaded with a trap
representation.

Simply put, you are not qualified to be giving advice to anyone.

I'll give you that, my specialty is doing all the Dirty NON-STANDARD work
you think can't get done.

Maybe you can tell us where you work so we can all steer clear of your
company's products.


Mark F. Haigh
(e-mail address removed)
 
C

ccwork

DHOLLINGSWORTH2 said:

No. What you said is: Keep in mind that a struct is just an int[],
with mapping handles for the "Programmer". This is wrong:
struct is not int[]. In other word, the offset of each struct member
is not always a multiple of fixed value. Say,
struct PACKED s
{
char a;
int b;
char c;
int d;
} x;
So &(x.a) has offset 0 to &x, &(x.b) has offset 1 to &x, &(x.c) has
offset 5 to &x and &(x.d) has offset 6 to &x. This is DIFFERENT from
array.
Obviously you gave a wrong example. And then you talked about data
bus, memory model, 64-bit, etc. All of them are dependent and not
standard C.
what I mean is that

char * s ="Some text in ram!";

the text "Some text in ram!" is actually stored in ram.
in contiguous chunks.

you could say char s[]; represents an area in ram at s,

I'M Saying that all of your ram can be looked at like
int []; instead of some char [], some word[]; etc.

When you store the data in a form the Hardware naturally proccessess you are
going to save more clock cycles than you will pull out optimizing your code
by hand.

Simple put, Streamlining your code, does more for you than optimizing. When
you use data structures that are not in anyway equivelant to the native
operation of your HW.

char s[] = "Some text in Ram";

as an int[]; is the same exact pattern in memory;

as a programmer you would have to unpack the integer to get the individual
char values. when you use char []; the packing, and unpacking is done
"behind the scene".

Lets say you have a struct :

struct myStruct {
short x;
short y;
short z;
} coord;

accessing coord.x means you are loading an intire register with int, and
croping it to obtain the short portion.

in effect, incrementing x, y, z means you have loaded at least one of these
twice, once you through it out, and the second time, you through the rest
out.

on a 64 bit machine, Which reads and writes 64 bits at a time, you would
read in each value, 16 bits, once, and get the other 48 bits with it, crop
it ( unpack) , increment it, add the 48 bits back in,( pack it ), then save
it back to ram.

you could read all 3 shorts at once by alligning your structure on a 64 bit
boundary, and inc each one in one clock cycle, and similarly in one write
cycle store all three values back.
or
(this was my original statement)
you can redifine mystruct
struct mystruct {
int x;
int y;
int z,
} coord;

now since the x, y, and z values match the register width, the Databus
width, you don't have to ( unpack) or (pack) anything,

of the three methods here,

the first one really helps the programmer, and saves space, at the expense
of clock cycles,

the second method saves space, and saves clock cycles at the expense of the
programmer,

while the third method uses more space, but huals ass, and takes just as
much time to code as the 1st method.

I'm not going to suggest not using char, You would have to write a sh__ load
of string proccessing code, ( "already been done").
But you can logically order the information, and resize some information to
give you the best of all 3 methods.

I hope this clears up what I was trying to say the first post.

I thought everyone could follow it ok. I was wrong.

IF( I_hurt_anyones_feeling)
{
my_Oppologies();
}
else O_FN_WELL;

Later,

Dan
 

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,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top