request for member in something not a structure or union

D

deepak

Hi Experts,

I'm getting this compilation error while trying to access a member in
structure.
at what time we will get this error message?

Thanks,
Deepak
 
N

Nick Keighley

I'm getting this compilation error while trying to access a member in
structure.
at what time we will get this error message?

thirteen o'clock

perhaps if you posted the code and the error message
we would have more chance of diagnosing your problem.
 
V

viza

Hi

I'm getting this compilation error while trying to access a member in
structure.

You have used the . operator where it isn't allowed.

Perhaps you need to replace it with -> (if what is to the left of it
is a pointer to a struct) or perhaps it just needs to be removed. It
is hard to say without seeing the part of the code.

HTH

viza
 
C

cr88192

pete said:
When you use a dot operator (.)
when you should be using an arrow operator (->)
instead.

now, a mystery, maybe somone will know:
why exactly is it that . and -> were originally made to be separate
operators anyways?...

what exactly is the cost of, say, a compiler implementor being lazy and
treating both cases as equivalent? (well, apart from maybe the risk of a
user writing code which will promptly break if used on a more
standards-conformant compiler...).

 
B

Bart

now, a mystery, maybe somone will know:
why exactly is it that . and -> were originally made to be separate
operators anyways?...

what exactly is the cost of, say, a compiler implementor being lazy and
treating both cases as equivalent? (well, apart from maybe the risk of a
user writing code which will promptly break if used on a more
standards-conformant compiler...).

I understand . and -> to do different things:

s.f accesses field f of struct s
p->f accesses field f of a struct pointed to by p. I think
equivalent to (*p).f.

Allowing (*p).f and p.f to be equivalent surely is a bad idea,
breaking the type system in an unnecessary way, and rendering code
less readable:

struct r *a, b; /* Hidden away somewhere */

x = a.f; /* These look seductively similar */
y = b.f; /* until you write: */
a = b; /* Error */

C doesn't allow dotted selections on a value other than for field
access, otherwise it would be clear that, when p is a pointer,
sometimes you want to access a property of the pointer, and not the
thing it points to; inventing a property .bytes:

size = p.bytes; /* Bytes in the pointer */
size = (*p).bytes; /* Bytes in the thing it points to */

This doesn't work well with -> however: p->bytes. In fact -> is an
ugly construct only tolerated because (*p). is worse! Pascal syntax
for this stuff is cleaner:

p {a pointer value}
p^ {the record p points to}
p^.f {field of the record p points to}
p.f {error}
p.bytes {bytes in the pointer}
p^.bytes {bytes in the record}
 
R

Richard Tobin

Bart said:
Allowing (*p).f and p.f to be equivalent surely is a bad idea,
breaking the type system in an unnecessary way

It doesn't break the type system at all. It just makes . a (more)
polymorphic operator, or alternatively introduces another automatic
conversion.

-- Richard
 
K

Keith Thompson

It doesn't break the type system at all. It just makes . a (more)
polymorphic operator, or alternatively introduces another automatic
conversion.

Right.

There are languages that allow the prefix to the "." "operator"
to be either a structure or a pointer to structure. Usually this
is done by making "." polymorphic, accepting either a structure or
a poitner as its prefix. (It's already polymorphic in the sense
that the prefix can be of any structure type.)

IMHO the "C-like" way to do this would have been to say that the
prefix to the "." "operator is *always* a pointer to struct, and
that an expression of struct type, if and only if it's followed by
".", decays to a pointer to the struct. This would be analagous
to the behavior of [], which acts as if it operated on an array
but really only operates on a pointer that results from a conversion.

Footnote 1: Replace "struct" with "struct or union" in the above.

Footnote 2: I put the word "operator" in quotation marks because "."
isn't really an operator; its right "operand" is not an expression.

Footnote 3: This scheme would work only when the struct-to-pointer
conversion is possible, i.e., when the struct expression is
actually the value of an object (otherwise there's nothing
to point to). This could cause problems for things like
function_returning_struct().member. (I think we already have such
problems when indexing into an array that's a member of a struct
returned by a function; where's the array object that the converted
pointer points to?)

Footnote 4: Obviously Ritchie *didn't* decide to define "." this
way, either by the conversion method or by making it polymorphic.
I wouldn't look for any deeper meaning in this decision. Probably
he just thought of accessing a member of a structure directly and
accessing the same member via a pointer to the structure as two
distinct operations, calling for two distinct syntaxes (or perhaps
the decision was inherited from B or BCPL). It's a decision that
could reasonably have been made either way.
 
L

lawrence.jones

cr88192 said:
why exactly is it that . and -> were originally made to be separate
operators anyways?...

Because back in the old days, there was no requirement that the left
operand have a structure or pointer to structure type. You could (and
people did!) use . or -> on integers, arrays, or whatever. Since the
operators do different things, they had to be distinct so the user could
specify which operation was desired. Now that the left operand is
restricted, there's no technical reason for having distinct operators.
Given that they already exist, however, there doesn't seem to be any
particular benefit to merging them and there would be real costs
involved to do so.
what exactly is the cost of, say, a compiler implementor being lazy and
treating both cases as equivalent? (well, apart from maybe the risk of a
user writing code which will promptly break if used on a more
standards-conformant compiler...).

Although you describe it as being "lazy", I can't imagine that
implementing one operator that can do either of two things is any less
work than implementing two operators each of which only does one thing.

-- Larry Jones

Years from now when I'm successful and happy, ...and he's in
prison... I hope I'm not too mature to gloat. -- Calvin
 
B

Bart

[email protected] (Richard Tobin) said:
It doesn't break the type system at all.  It just makes . a (more)
polymorphic operator, or alternatively introduces another automatic
conversion.

Right.

There are languages that allow the prefix to the "." "operator"
to be either a structure or a pointer to structure.  Usually this
is done by making "." polymorphic, accepting either a structure or
a poitner as its prefix.  (It's already polymorphic in the sense
that the prefix can be of any structure type.)

IMHO the "C-like" way to do this would have been to say that the
prefix to the "." "operator is *always* a pointer to struct, and
that an expression of struct type, if and only if it's followed by
".", decays to a pointer to the struct.  This would be analagous
to the behavior of [], which acts as if it operated on an array
but really only operates on a pointer that results from a conversion.

So the left side side of "." is not just a struct type, but any chain
of pointers to a struct, multi-dereferenced as necessary to get at the
struct that "." needs? (This shows up a weakness in -> which can only
deal with one dereference at a time.)

Workable, but just seems to lack a certain amount of rigour. And
throws away useful information from the source (now: s *must* be a
struct in s.f; "p" *must* be a pointer to a struct in p->f).

And it loses the possibility of being able to select an attribute of
the pointer using dot notation (although C doesn't have anything like
this, at present).
 
C

Chris Torek

So the left side side of "." is not just a struct type, but any chain
of pointers to a struct, multi-dereferenced as necessary to get at the
struct that "." needs? (This shows up a weakness in -> which can only
deal with one dereference at a time.)

In the languages that I know about that allow either structure
or pointer-to-structure before ".member", no: only one "level"
of pointer-ness is allowed. That is, in a modified C in which
"p.foo" were accepted given "struct S *p", if this modified C
were like these other languages, given "struct S **pp;", "pp.foo"
would still be an error.

(In this modified C, however, you could then use "(*pp).foo"
the way you now can use "(*pp)->foo".)

In early C, the "->" and "." "operators" (I use quotes around
operator for the same reason Keith Thompson did) never bothered to
check the types of their left-hand-side "operands". The following
were allowed, and both were in fact used:

struct {
char lo, hi;
};
int i;
...
printf("%o %o\n", i.lo, i.hi);

struct {
int csr;
int bar;
int cnt;
};
...
0777440->bar = addr;

(Do not try this with a modern C compiler. :) ) The -> "operator"
simply *assumed* the left "operand" was a pointer and followed it,
while the "." "operator" simply *assumed* that the right "operand"
was an appropriate structure. Both then simply added the member-offset
to the "address" derived by lvaule-style evaluation of the thing
on the left, and treated the resulting address as if it were an
object whose type was given by the member-name on the right.

Because -> and . did not look at their left sides, all structure
(and union) member names *had* to be unique. That is, doing
something like:

struct list_of_X {
int x_value;
struct list_of_X *next;
};

struct list_of_Y {
double y_value;
double y_associate;
struct list_of_Y *next;
};

would fail, because the member named "next" had to have two different
offsets (2 and 10, since sizeof(int)==2 in this early version of
C). The compiler did not bother to see whether p->next or t.next
wanted an "X next" or a "Y next", so having two different kinds of
"next"s would be impossible. This is why Unix-like systems have,
for instance, all of the members of "struct stat" named "st_foo":
the st_ prefix made all the member names distinct, so that you
could use both a "struct stat" (with its st_ino) and a "struct
direct" (with its d_ino) without having the two "ino" member names
clashing.
 
R

Richard Tobin

Bart said:
So the left side side of "." is not just a struct type, but any chain
of pointers to a struct, multi-dereferenced as necessary to get at the
struct that "." needs? (This shows up a weakness in -> which can only
deal with one dereference at a time.)
Workable, but just seems to lack a certain amount of rigour.

If it were just done for ".", it would seem a bit inconsistent. But
Algol 68 always performed any of a certain set of "coercions"
necessary to get a suitable type. If you assigned (the equivalent of)
an int *** to an int, it would dereference it three times.

-- Richard
 
C

cr88192

Because back in the old days, there was no requirement that the left
operand have a structure or pointer to structure type. You could (and
people did!) use . or -> on integers, arrays, or whatever. Since the
operators do different things, they had to be distinct so the user could
specify which operation was desired. Now that the left operand is
restricted, there's no technical reason for having distinct operators.
Given that they already exist, however, there doesn't seem to be any
particular benefit to merging them and there would be real costs
involved to do so.

yes, ok.

seems I am not so fammiliar then with C from that era (I am not particularly
sure then how struct or union access would work at all...).

as noted, there is a cost, but more in the form of someone accidentally
writing non standards-conformant code. existing code works fine (there not
being cases where both work but have different meanings), so this is not as
much of a problem.

Although you describe it as being "lazy", I can't imagine that
implementing one operator that can do either of two things is any less
work than implementing two operators each of which only does one thing.

one can be lazy, because at nearly every stage of the compilation process
(much past the parser), they can be treated as one operator, and doing it
this way requires less effort (we would have, one case for '.' and another
case for '->').

this is infact less work in general (less cases is easier than more cases).

and, in what way to either of these operators only do one thing?
we already have to figure out which types they are being used with, and to
handle a pointer-to-case along with a raw struct case (often internally
represented by passing a pointer anyways), there is no real savings in work
by having them split (actually, there is more work, since then one is
obligated to diagnose their accidental misuse, ...).

(we are long past the days where we can claim any one operator does any one
thing, in fact, any one operator does any number of a wide variety of
possible but related things...).


now, when one gets a little closer to the final code generation, it is
fairly trivial to recognize what types are being applied (after all, we have
to do this much already), and so, slightly different code is generated (from
this point on, they are different operators, but past this point, any real
notions of 'structs' or 'operators' have already since gone away, us having
moved into the land of register allocation and CPU-level operations).

of course, in my tweakery, I went and used this operator for a few
non-struct types as well, such as vector access and permutations (like in
GLSL...).

and, if I were to add special operators for vector operations, I would end
up having to deal with them at each and every stage in the compilation
process, but overloading them, I only have to deal with this difference once
it actually matters...
 
K

Keith Thompson

Bart said:
There are languages that allow the prefix to the "." "operator"
to be either a structure or a pointer to structure.  Usually this
is done by making "." polymorphic, accepting either a structure or
a poitner as its prefix.  (It's already polymorphic in the sense
that the prefix can be of any structure type.)

IMHO the "C-like" way to do this would have been to say that the
prefix to the "." "operator is *always* a pointer to struct, and
that an expression of struct type, if and only if it's followed by
".", decays to a pointer to the struct.  This would be analagous
to the behavior of [], which acts as if it operated on an array
but really only operates on a pointer that results from a conversion.

So the left side side of "." is not just a struct type, but any chain
of pointers to a struct, multi-dereferenced as necessary to get at the
struct that "." needs? (This shows up a weakness in -> which can only
deal with one dereference at a time.)

Hmm. I hadn't thought about that. Now that I do, I think the answer
is no. Given this hypothetical feature as I've described it, if the
prefix of "." is a pointer to pointer to struct, it wouldn't decay;
the implicit conversion would be defined only for a pointer to struct.

Since the language doesn't actually have this feature, of course,
you're free to define it any way you like, but personally I don't
think the extra complication is worthwhile. I don't think accessing a
member given a pointer-to-pointer-to-struct is nearly as common as
accessing a member given either a pointer-to-struct or a struct, and I
think the pointer-to-pointer-to-struct case is unusual enough to call
for a distinct syntax. (The language I'm familiar with that does
allow "foo.bar" where foo is either a structure or a pointer to
structure doesn't allow it to be a pointer to pointer to structure;
when I used that language, I never missed the ability to do that. (It
was Ada.))

[snip]
 

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,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top