--- Recap: Qs. about struct --- 
Author Message
 --- Recap: Qs. about struct ---

Hi all:

Thanks for replying. Your messages were quite informative and I really
appreciate the time you spent on the reply. And before I forget, A happy
and prosperous New Year.

Let me recap my current understanding as to the way things work:

If have a structure defined as:

struct foo
{
  long  x;
  long  y;

Quote:
} mystruct;

then:

1) Internally, in the compiler's symbol table, struct is assigned an
address during compilation. Say this address is 1000.

-----------------------------------------------------------------

2) An amount of space equal to 2 longs ( x and y ) is reserved after this
address. The amount of space can even be more than 2 longs if things like
padding are done. If the compiler needs to assign locations for more
variables it will skip over this space.

-----------------------------------------------------------------

3) when the compiler sees anything like:

a) mystruct = 5 - then it will complain because it can't parse that according
to the rules of the language.
b) mystruct.x  = 5 - then it will add the address of mystruct ( = 1000 )
to the offset of x ( = 0 in this case) and store 5 in 1000 i.e
[1000] <- 5

-----------------------------------------------------------------

4) If I now define a pointer to this structure:

struct foo *ptrToMyStruct

ptrToMyStruct = &mystruct then:

a) the compiler assigns a memory location to ptrToMyStruct ( say 1200)

b) It then puts the address of mystruct( = 1000) into address 1200. i.e
[1200] = 1000

-----------------------------------------------------------------

5) If I say:

*ptrToMyStruct then I get the value of the whole structure because I defined
the pointer to point to all of the structure  foo. Therefore  the compiler
reads  sizeof(mystruct) bytes starting from 1000.

However if I cast ptrtoMyStruct into a long i.e.

(long) *ptrToMyStruct then the compiler reads the first 4 bytes from 1000
and  I get mystruct.x !

After the cast ptrToMyStruct[2] will only give methe value of y (mystruct.y)
if there is no padding between x and y.

-----------------------------------------------------------------

6) Lastly, I have the following follow up question. ( Hope I'm not nitpicking
here )

We know that when the compiler sees mystruct.y it outputs
 * ( &mystruct + sizeof(x) + any padding )

But when the compiler sees:

 *(ptrToMyStruct).x or .y        [ where ptrToMyStruct = &mystruct = 1000 ]

how exactly does it emit the code?

Does it :

a) *First*, when it sees (*ptrToMyStruct) it reads sizeof(mystruct) bytes
from 1000. If the structure is 8 bytes ( no padding) then it would read
bytes 1000 - 1008. ( This is the behavior I would expect; see 5 above).
It then keeps only the bytes that the variable x or y is contained in.

                                        or

b) It just does * ( &mystruct + sizeof(x) + any padding ) much like when
it sees mystruct.x

This would mean a delayed pointer indirection i.e the compiler will
see the expression "(*ptrToMyStruct).x" and evaluate is as a
whole rather than evaluating it part by part. In that case
(*ptrToMyStruct).x will be as fast as mystruct.x

-----------------------------------------------------------------

Note: As several people pointed out, some variables might be stored in
registers etc. For e.g. ptrToMyStruct might actually be stored in a register.
That shouldn't change the logic above, but in case it does, ignore the
register case please...

Hursh

P.S: In my original post I was doing something like:

printf("The value is %ld", *ptrToMyStruct) which might or might not
give the first element of the structure. The main thing I learnt was
that *ptrToMyStruct is a pointer to the WHOLE structure and reading
it as %ld can give unpredicatable results.



Sun, 27 Jun 1999 03:00:00 GMT  
 --- Recap: Qs. about struct ---

Quote:

> Let me recap my current understanding as to the way things work:

Since you seem to be aiming for a pretty complete understanding
of this, I'm going to get pretty nitpicky here; be forewarned.

Quote:
> If have a structure defined as:

> struct foo
> {
>   long  x;
>   long  y;
> } mystruct;

> then:

> 1) Internally, in the compiler's symbol table, struct is assigned an
> address during compilation. Say this address is 1000.

Actually, few compilers assign addresses at compilation time.
What usually happens is that the compiler places a record in
the object code saying "there will be an object of size such-
and-such and the remainder of the object code will refer to
this by such-and-such an ID".  Subsequent references to mystruct
will refer to that ID.  The linker (or loader, or relocator, or
binder, or whatever) is responsible for actually setting the
address and resolving the references.  Exactly how this is done
is very machine and o/s dependent.

Quote:
> 2) An amount of space equal to 2 longs ( x and y ) is reserved after this
> address. The amount of space can even be more than 2 longs if things like
> padding are done. If the compiler needs to assign locations for more
> variables it will skip over this space.

Good enough, though I'm not entirely sure what the last sentence
means.

Quote:
> 3) when the compiler sees anything like:

> a) mystruct = 5 - then it will complain because it can't parse that according
> to the rules of the language.
> b) mystruct.x  = 5 - then it will add the address of mystruct ( = 1000 )
> to the offset of x ( = 0 in this case) and store 5 in 1000 i.e
> [1000] <- 5

Okay.  But I think you'd be better off thinking in terms of a more
symbolic assembly language, one where (b) could be expressed as

    [mystruct + offset x] <- 5

Here mystruct is a symbolic value that will be replaced by the
linker (or whatever) with the actual address of mystruct.
"offset x" is known to the compiler.  Most object code formats
that I'm familiar with allow constructs that tell the linker
to do the addition; that is, the actual machine code wouldn't
be

    move r,mystruct
    add  r,offset x
    mov  [r],5

but rather

    move r,mystruct+offset x
    mov  [r],5

Of course, this only happens this way becase mystruct is static.
If mystruct were a local variable in a subroutine, the compiler
would generally generate all references as offsets from a frame
pointer of some sort, and the linker would not be involved at
all.

In other words, given code like this:

    void myfunc( void )
    {
        struct foo mystruct;
        mystruct.x = 5;
    }

a compiler will usually generate something like:

    move r0,fp
    add  r0,offset mystruct + offset x
    move [r0],5

Note that this only uses offsets known to the compiler; the
linker need not be involved at all.

Quote:
> 4) If I now define a pointer to this structure:

> struct foo *ptrToMyStruct

> ptrToMyStruct = &mystruct then:

> a) the compiler assigns a memory location to ptrToMyStruct ( say 1200)

> b) It then puts the address of mystruct( = 1000) into address 1200. i.e
> [1200] = 1000

Again, how about using a symbolic pseudo-assembler and saying:

    [ptrToMyStruct] = mystruct

Trying to think in terms of concrete addresses is often misleading.
Try to keep your thinking symbolic as much as possible.

Quote:
> 5) If I say:

> *ptrToMyStruct then I get the value of the whole structure because I defined
> the pointer to point to all of the structure  foo. Therefore  the compiler
> reads  sizeof(mystruct) bytes starting from 1000.

"refer to" would be a better verb than "get" and "read" here.  Since
you aren't doing anything with *ptrToMyStruct, the compiler is not
generating code to "get" or "read" anything.

Quote:
> However if I cast ptrtoMyStruct into a long i.e.

> (long) *ptrToMyStruct then the compiler reads the first 4 bytes from 1000
> and  I get mystruct.x !

Well, no.  The construct you show:

    (long)*ptrToMyStruct

is quite meaningless.  You're casting a structure to a long, which
makes no sense whatsoever.  Perhaps you mean:

    *(long *)ptrToMyStruct

which casts a pointer to a struct foo to a pointer to long and then
dereferences it.  Most machines I know of will indeed give you the
value of the x field of the struct foo, but I certainly wouldn't
guarantee it.  I think this is undefined behavior.  (Someone will
be sure to correct me on that if I'm wrong!)

Quote:
> After the cast ptrToMyStruct[2] will only give methe value of y (mystruct.y)
> if there is no padding between x and y.

Absolutely not.  ptrToMyStruct[2] refers to the third element of
an array of "struct foo"s.  Since ptrToMyStruct was assigned the
address of only a single structure, this is undefined behavior.
What the compiler will do is emit code that adds 2 * sizeof foo
to ptrToMyStruct and then dereference that however you designate
in the remainder of the expression.

If you mean

    ((long *)ptrToMyStruct)[2]

then this would refer to a long which is 2 * sizeof long bytes
beyond the beginning of mystruct (assuming ptrToMyStruct is
assigned &mystruct as above).  Assuming we have no packing
in the structure, this would not be y anyway; it would be
the next long beyond that (actually, the sizeof long bytes
interpretted as a long).

Quote:
> 6) Lastly, I have the following follow up question. ( Hope I'm not nitpicking
> here )

> We know that when the compiler sees mystruct.y it outputs
>  * ( &mystruct + sizeof(x) + any padding )

Better to interpret this as

    &mystruct + offset y

Quote:
> But when the compiler sees:

>  *(ptrToMyStruct).x or .y        [ where ptrToMyStruct = &mystruct = 1000 ]

> how exactly does it emit the code?

It doesn't; it generates a syntax error.  You're trying to
treat a pointer as a structure.  You probably mean:

    (*ptrToMyStruct).x

which is exactly equivalent to

    ptrToMyStruct->x

Quote:
> Does it :

> a) *First*, when it sees (*ptrToMyStruct) it reads sizeof(mystruct) bytes
> from 1000. If the structure is 8 bytes ( no padding) then it would read
> bytes 1000 - 1008. ( This is the behavior I would expect; see 5 above).
> It then keeps only the bytes that the variable x or y is contained in.

No, you haven't told it to _read_ anything; you have merely refered
to a structure member.  Let's assume we're talking about something like:

    long l = ptrToMyStruct.x;

It would not read the entire structure and then extract just the
appropriate member; it would generate code to read just that one
member.

Quote:
>                                         or

> b) It just does * ( &mystruct + sizeof(x) + any padding ) much like when
> it sees mystruct.x

Yes, this one.

Quote:
> This would mean a delayed pointer indirection i.e the compiler will
> see the expression "(*ptrToMyStruct).x" and evaluate is as a
> whole rather than evaluating it part by part. In that case
> (*ptrToMyStruct).x will be as fast as mystruct.x

Well, not necessarily.  The line

    l = (*ptrToMyStruct).x;

would compile to something like:

    move ro,[ptrToMyStruct]     // assume ptrToMyStruct is not in a register
    move r1,[ro+offset x]
    move [l],r1

(If the architecture allows memory-to-memory moves, the 2nd and 3rd
lines may be combined.)

On the other hand, the line

    l = mystruct.x;

would compile to something like

    move r0,[mystruct+offset x]
    move [l],r0

(Again, these lines may be combined on some machines.)

Quote:
> Note: As several people pointed out, some variables might be stored in
> registers etc. For e.g. ptrToMyStruct might actually be stored in a register.
> That shouldn't change the logic above, but in case it does, ignore the
> register case please...

I did.

Quote:
> P.S: In my original post I was doing something like:

> printf("The value is %ld", *ptrToMyStruct) which might or might not
> give the first element of the structure. The main thing I learnt was
> that *ptrToMyStruct is a pointer to the WHOLE structure and reading
> it as %ld can give unpredicatable results.

Yes.  Not knowing what else to do with it, the compiler would
generate code to place the entire structure on the stack (let's
assume a stack-based machine for simplicity here), and then
printf would grab some unpredictable long-sized portion of
it, interpret those bytes as a long, and print it.  My guess
is that most compilers would print ptrToMyStruct->x, but I
wouldn't put money on it.

Now, with that all said, my best advice to you is to ignore
it all.  It is sometimes handy to know this sort of stuff
when debugging, but get to know the language inside and
out in terms of the language itself, not in terms of how
it is implemented.

Once you get comfortable with the language, if you're still
curious about this stuff, use a compiler flag to generate
assembler output (most compilers I know of have such an
option) and compare that to the C code.



Wed, 30 Jun 1999 03:00:00 GMT  
 --- Recap: Qs. about struct ---

In places below there are parenthetical `pedantic'ities. Ignore them
unless you are a pedant and know the standard well.

Quote:

> Let me recap my current understanding as to the way things work:

> If have a structure defined as:

> struct foo
> {
>   long     x;
>   long  y;
> } mystruct;

> then:

> 1) Internally, in the compiler's symbol table, struct is assigned an
> address during compilation. Say this address is 1000.

You probably meant `mystruct' is assigned an address.

It is more useful to think of this and the next point together as
saying that a certain space is reserved in memory for this
object. Memory in the computer is identified by addresses and
naturally, the bytes this object is composed of all have addresses. In
particular, the beginning of this object has an address.

Note that addresses need not be simple things like numbers. The
address may be more complicated like the 5th byte on the 10th memory
bank. Nevertheless, the compiler (to follow the spirit of the language
at least) is obliged to arrange all memory into a sequential order (in
some form which is `natural' to someone who knows how the memory is
actually organized). So, when you say that the address is 1000, you
are actually simplifying things a little bit: you probably mean that
it is the 1000th byte in this sequential order. The difference is
important because this sequential order may have gaps: thus mystruct
begins at 1000 does not imply that anything begins at 999, say. In
fact, 999 may not even be a valid address for this machine.

Quote:
> -----------------------------------------------------------------

> 2) An amount of space equal to 2 longs ( x and y ) is reserved after this
> address. The amount of space can even be more than 2 longs if things like
> padding are done. If the compiler needs to assign locations for more
> variables it will skip over this space.

This is correct. The amount of space allocated can be found by asking
for `sizeof mystruct'. Because of the memory architecture, the
compiler may decide to skip more space than that (i.e. the location
immediately following mystruct may not be used for
anything). (pedantic reading of the standard implying that nothing can
follow this object immediately ignored as being nonsensical.) Notice
that the compiler may thus decide to waste space if it wants. Of
course, a compiler that wastes space for absolutely no reason is not a
good compiler; but the programmers should not assume that the compiler
has no good reason.

Furthermore, if you had said something like

struct x mystruct1, mystruct2, mystruct3;

the compiler may decide to put mystruct3 first, mystruct1 next and
mystruct2 at the end if that will result in more efficient code, or
for any other reason that it chooses. All you know is that the storage
will not overlap.

And, yet-furthermore, if the compiler can get away with it, it may decide not to reserve any space for it whatsoever. Thus a compiler that sees code like

int f(void) {
  struct foo {
        long x;
        long y;
  } mystruct;
  mystruct.x = 5;
  return mystruct.x;

Quote:
}

might decide that it needn't reserve any space for anything: when the
function is called, it may just decide to return 5!

Quote:
> -----------------------------------------------------------------

> 3) when the compiler sees anything like:

> a) mystruct = 5 - then it will complain because it can't parse that according
> to the rules of the language.
> b) mystruct.x  = 5 - then it will add the address of mystruct ( = 1000 )
> to the offset of x ( = 0 in this case) and store 5 in 1000 i.e
> [1000] <- 5

Correct (with all the proviso explained above). To be more precise, it
stores 5 into the long that starts at address 1000. [1000] is a
confusing notation: do you mean the byte at address 1000, the long
starting at the address 1000 or the whole struct starting at the
address 1000?

Quote:
> -----------------------------------------------------------------

> 4) If I now define a pointer to this structure:

> struct foo *ptrToMyStruct

> ptrToMyStruct = &mystruct then:

> a) the compiler assigns a memory location to ptrToMyStruct ( say 1200)

> b) It then puts the address of mystruct( = 1000) into address 1200. i.e
> [1200] = 1000

Yes. Again, the correct way of thinking about it is that the address
of the memory 1000 (which as I stated before may be more complicated
thing representing the 5th byte in the 10th memory bank, possibly
represented by the bit pattern 1100000000011) into the object of type
`struct foo*' which starts at the memory address 1200. Again, [1200]
is a confusing notation: somebody could erroneously think of it as the
byte at address 1200.

Quote:
> -----------------------------------------------------------------

> 5) If I say:

> *ptrToMyStruct then I get the value of the whole structure because I defined
> the pointer to point to all of the structure  foo. Therefore  the compiler
> reads  sizeof(mystruct) bytes starting from 1000.

Yes. And the compiler knows that you are getting a struct. It is not
only the size of what is retrieved: it is rather a value with a
certain type.

Quote:
> However if I cast ptrtoMyStruct into a long i.e.

> (long) *ptrToMyStruct then the compiler reads the first 4 bytes from 1000
> and  I get mystruct.x !

First, that does not cast is *not* casting ptrtoMyStruct, it is trying
to cast the result of *ptrToMyStruct, i.e. here you are casting the
value mystruct (not the address 1000) into a long. However, struct
values cannot be cast at all!

If instead you wrote `(long *)ptrToMyStruct', you would have been
saying that you wanted a pointer which points to an object of type
long starting at the same point as ptrToMyStruct points. Note that
this is a different pointer, and may be represented in a different way
in the computers registers. The compiler however knows that when you
dereference this one (i.e. when you say `*(long *)ptrToMyStruct', it
is supposed to fetch a long from there, and not the whole struct.

Now, the standard guarantees that there is no padding at the beginning
of the struct, so an object of type long that starts at the same point
as the struct is naturally mystruct.x. In other words, you are
guaranteed *(long *)ptrToMyStruct = mystruct.x.

(I did skip over a little bit of pointless pedantry in the above
explanation. The last statement is pedantically correct, however).

Quote:

> After the cast ptrToMyStruct[2] will only give methe value of y (mystruct.y)
> if there is no padding between x and y.

I do not understand `after the cast'. (long *)ptrToMystruct does not
change the type or value of ptrToMystruct at all! What it does is that
it asks for a pointer to long which starts at the same point as
ptrToMystruct points to. This value is not stored anywhere unless you
ask to store it.

ptrToMystruct[2] always means give me the struct which is obtained
after skipping over two structs starting at the position ptrToMystruct
points to. As there is only one struct at that position, it is
impossible to skip over two structs, far less to get to the third
struct after that as you have requested. The code may die a horrible
death at this point, or if that memory actually corresponds to
something, you may get garbage from that memory location.

If you had written ( (long*)ptrToMystruct ) [2], you would have
1) first constructed a pointer to mystruct.x (as discussed earrlier)
2) skipped over two longs starting at that point (two longs because
the type of the pointer is long*, and you said [2] after that
pointer).
3) referred to the long at that position. Note that even without
padding there is no third long to reach!

Even if this were not the case, such pointer arithmetic is frowned
upon by the standard. In particular, (&mystruct.x)[1] is not allowed
by the standard: you are supposed to use [] when you have declared an
array of objects, not simply to move around in memory arbitrarily. The
compiler is allowed to detect your trickery and punish you for that
:-)

Quote:
> -----------------------------------------------------------------

> 6) Lastly, I have the following follow up question. ( Hope I'm not nitpicking
> here )

You actually are :-)

Quote:

> We know that when the compiler sees mystruct.y it outputs
>  * ( &mystruct + sizeof(x) + any padding )

No!!! &mystruct + sizeof(x) would mean skip over sizeof(x) structs
starting at the position &mystruct! (Why? Because &mystruct has type
(struct foo *)). Remember pointer addition does not add *bytes*, it
adds whatever units are being pointed to as determined by the *type*
of the pointer. In C, *never* think of a value without also thinking
of its type.

If you really want to think in terms of bytes, *convert* the pointer
to a byte pointer. Finally, to retrieve the long object, *convert* the
pointer back to an appropriate type. In other words,

mystruct.y == * (long*) ( (unsigned char*)&mystruct + offsetof(struct foo,y))

where offsetof (a macro defined for you if you #include <stddef.h>)
gives you sizeof(mystruct.x)+padding in this case. (Incidentally, I
always think `unsigned char' when I think byte. So, I did not use
(char*), which would also have done in this context). (pedantry about
pointer arithmetic is ignored in the above.)

Note that the language is concerned only with the results. Whether it
reads the whole struct and keeps only the relevant portion, or it only
reads the portion it needs depends on your compiler. A good compiler
will certainly not read the whole struct and waste time if it has no
good reason to do so. (It can be requested to read the whole struct by
appropriate use of volatile etc., but how binding such a request is,
is a whole different topic altogether).

You are however supposed to make sure that the whole struct exists so
that it can be read. Apart from pedantry, this is always the case
unless you are doing something you shouldn't be doing anyway.

- Show quoted text -

Quote:
> But when the compiler sees:

>  *(ptrToMyStruct).x or .y        [

...

read more »



Wed, 30 Jun 1999 03:00:00 GMT  
 --- Recap: Qs. about struct ---

Quote:

>Hi all:
>Thanks for replying. Your messages were quite informative and I really
>appreciate the time you spent on the reply. And before I forget, A happy
>and prosperous New Year.
>Let me recap my current understanding as to the way things work:
>If have a structure defined as:
>struct foo
>{
>  long      x;
>  long  y;
>} mystruct;
>then:
>1) Internally, in the compiler's symbol table, struct is assigned an

                                                  ^^^ I assume you mean
                                                      mystruct here.

Quote:
>address during compilation. Say this address is 1000.
>-----------------------------------------------------------------
>2) An amount of space equal to 2 longs ( x and y ) is reserved after this
>address. The amount of space can even be more than 2 longs if things like
>padding are done. If the compiler needs to assign locations for more
>variables it will skip over this space.
>-----------------------------------------------------------------
>3) when the compiler sees anything like:
>a) mystruct = 5 - then it will complain because it can't parse that according
>to the rules of the language.
>b) mystruct.x  = 5 - then it will add the address of mystruct ( = 1000 )
>to the offset of x ( = 0 in this case) and store 5 in 1000 i.e
>[1000] <- 5
>-----------------------------------------------------------------
>4) If I now define a pointer to this structure:
>struct foo *ptrToMyStruct
>ptrToMyStruct = &mystruct then:
>a) the compiler assigns a memory location to ptrToMyStruct ( say 1200)
>b) It then puts the address of mystruct( = 1000) into address 1200. i.e
>[1200] = 1000
>-----------------------------------------------------------------
>5) If I say:
>*ptrToMyStruct then I get the value of the whole structure because I defined
>the pointer to point to all of the structure  foo. Therefore  the compiler
>reads  sizeof(mystruct) bytes starting from 1000.
>However if I cast ptrtoMyStruct into a long i.e.
>(long) *ptrToMyStruct then the compiler reads the first 4 bytes from 1000
>and  I get mystruct.x !

No way! If you cast "ptrToMyStruct" to a pointer to long, and then
use the "*" operator on the casted pointer, you will indeed get
the long stored in the first element of your struct, since there
cannot be padding before the first element.

Casting the struct to a long need not be supported.

A long need not have a size of 4 bytes, but that's a different topic.

Quote:
>After the cast ptrToMyStruct[2] will only give me the value of y (mystruct.y)
>if there is no padding between x and y.

Maybe, but since you can never be sure that there is no padding
between the two elements, why should you care?

BTW, to access the second of two consecutive longs, you would use
"[1]", so, if we assume that the two longs are indeed stored
without padding, something like

  ((long *)ptrToMyStruct)[1]

might be an expression that renders the value of "ptrToMyStruct->y".

Quote:
>-----------------------------------------------------------------
>6) Lastly, I have the following follow up question. ( Hope I'm not nitpicking
>here )
>We know that when the compiler sees mystruct.y it outputs
> * ( &mystruct + sizeof(x) + any padding )

How do you know? &mystruct is a pointer to a "struct foo". Adding
"sizeof(x) + any padding" to  it will lead to a position that is
well beyond the original struct in most cases. I would agree that
it will produce something that is roughly equivalent to

  *((long *)(((char *)&mystruct) + offsetof(struct foo, y)));

but I would not rely on the fact that a code cenerator emits
_exactly_ the same code for both expressions.

Quote:
>But when the compiler sees:
> *(ptrToMyStruct).x or .y        [ where ptrToMyStruct = &mystruct = 1000 ]
>how exactly does it emit the code?

Did you try to compile this? Successful compilation need not mean a lot,
but if some compilers reject your code, you could take that as a hint
that there might be something wrong with your understanding of the
language definition.

You could either write

  (*ptrToMyStruct).x

or

  ptrToMyStruct->x

Quote:
>Does it :
>a) *First*, when it sees (*ptrToMyStruct) it reads sizeof(mystruct) bytes
>from 1000. If the structure is 8 bytes ( no padding) then it would read
>bytes 1000 - 1008. ( This is the behavior I would expect; see 5 above).
>It then keeps only the bytes that the variable x or y is contained in.
>                                    or
>b) It just does * ( &mystruct + sizeof(x) + any padding ) much like when
>it sees mystruct.x

The way of thinking shown in this article is a sign of thinking too
close to the machine. "ptrToMyStruct->x" is an expression that
can be evaluated in a lot of different ways on the machine level.
If your CPU supports an addressing mode like "address register
indirect with offset", the compiler can use that addressing mode
to evaluate the expression. If loading the whole struct is an
efficient operation for some reason, the compiler may choose to
do this, too.

However, of the two scenarios described, the first is the more
probable one for most architectures.

Quote:
>This would mean a delayed pointer indirection i.e the compiler will
>see the expression "(*ptrToMyStruct).x" and evaluate is as a
>whole rather than evaluating it part by part.

The compiler may even "know" what is stored in "ptrToMyStruct->x"
because it has been stored there in a preceeding statement, and
use the stored result of that preceeding expression (from a register
or a known memory location) instead of any access to memory based
on the current value of "ptrToMyStruct".

Quote:
>In that case
>(*ptrToMyStruct).x will be as fast as mystruct.x

This is a "non sequitur". Access to a "local" struct may happen
through a special, stack pointer relative, addressing mode, and
a compiler may fail to recognize that this special addressing
mode can be used if the expression uses a pointer instead of
a local variable, even if the pointer points to a local variable.

The code emitted for both statements might  even depend on
the current set of command line options passed to the
compiler, and you should be interested in the details of
the code emitted for certain expressions _only_ if you
have identified the expression in question as a bottleneck
during profiling.

Kurt

--
| Kurt Watzka                             Phone : +49-89-2180-6254



Wed, 30 Jun 1999 03:00:00 GMT  
 --- Recap: Qs. about struct ---



Quote:
>Casting the struct to a long need not be supported.

Indeed trying to cast a struct to anything at all or trying to cast
anything to a struct is a constraint violation and requires a diagnostic
(both the operand and target type of a cast are required to have scalar
type).

...

Quote:
>Maybe, but since you can never be sure that there is no padding
>between the two elements, why should you care?

>BTW, to access the second of two consecutive longs, you would use
>"[1]", so, if we assume that the two longs are indeed stored
>without padding, something like

>  ((long *)ptrToMyStruct)[1]

>might be an expression that renders the value of "ptrToMyStruct->y".

There again it might not. Even if there is no padding this exceeds array
bounds (for the purposes of pointer arithmetic an object of non-array type
behaves like an array of 1 element of that type).

--
-----------------------------------------


-----------------------------------------



Sun, 04 Jul 1999 03:00:00 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. strtok() Qs.

2. Qs of getrusage()

3. Qs on Function Call on Array

4. C's Qs

5. four Qs about C

6. Borland open/_rtl_open/sopen Qs

7. Various Qs on raw_interfaces_only, no_namespace, throw, smartpointers

8. VERBATUM EXAM Qs 50929

9. 2 GUI Qs

10. Qs about MS VC++

11. Two Qs on MFC in VC.NET

12. 2 GUI Qs

 

 
Powered by phpBB® Forum Software