Why won't the compiler tell??

M

Mark Rance

Consider this:

typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

The only way this works is if I have declared a variable of type foo...yet
the compiler knows quite well what the answer to what I am asking.

This just seems like something the compilers should be able to handle.

-Mark
 
C

Claudio Puviani

Mark Rance said:
Consider this:

typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

The only way this works is if I have declared a variable of type foo...yet
the compiler knows quite well what the answer to what I am asking.

This just seems like something the compilers should be able to handle.

sizeof gives you the size of a type (or the size of the type of the result of
an expression). 'foo.b' is neither, nor is it a valid syntactic construct. One
way to get the size is to do sizeof(((foo *)0)->b). There's no danger because
the expression never gets evaluated and so you're not actually dereferencing a
zero pointer. Only the type of the result is determined.

Claudio Puviani
 
J

Julie

Claudio Puviani wrote:
[snip]
sizeof gives you the size of a type (or the size of the type of the result of
an expression). 'foo.b' is neither, nor is it a valid syntactic construct. One
way to get the size is to do sizeof(((foo *)0)->b). There's no danger because
the expression never gets evaluated and so you're not actually dereferencing a
zero pointer. Only the type of the result is determined.

As an aside, did you see how much crap I got from posting my compiler's
implementation of the offsetof macro that is based on similar non-evaluated
dereferencing? I was trying to point out that there are legitimate uses for
macros, and instead several found course to attack me because that
implementation leads to undefined behavior in their mind.
 
C

Claudio Puviani

Julie said:
Claudio Puviani wrote:
[snip]
sizeof gives you the size of a type (or the size of the type of the result of
an expression). 'foo.b' is neither, nor is it a valid syntactic construct. One
way to get the size is to do sizeof(((foo *)0)->b). There's no danger because
the expression never gets evaluated and so you're not actually dereferencing a
zero pointer. Only the type of the result is determined.

As an aside, did you see how much crap I got from posting my compiler's
implementation of the offsetof macro that is based on similar non-evaluated
dereferencing? I was trying to point out that there are legitimate uses for
macros, and instead several found course to attack me because that
implementation leads to undefined behavior in their mind.

No, I missed that. It's a surprising reaction, since most C++ programmers have
a similar macro (usually implementing OFFSET_OF) somewhere in their toolbox.

Claudio Puviani
 
S

Siemel Naran

Mark Rance said:
typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

Does sizeof(foo::b) work?
 
B

Buster

Mark said:
Consider this:

typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

The only way this works is if I have declared a variable of type foo...yet
the compiler knows quite well what the answer to what I am asking.

This just seems like something the compilers should be able to handle.

size_t x = sizeof foo ().b;
 
J

Jeff Schwab

Claudio said:
Julie said:
Claudio Puviani wrote:
[snip]
sizeof gives you the size of a type (or the size of the type of the result
of
an expression). 'foo.b' is neither, nor is it a valid syntactic construct.
One
way to get the size is to do sizeof(((foo *)0)->b). There's no danger
because
the expression never gets evaluated and so you're not actually

dereferencing a

If you're not willing to get something better than Outlook Express to
avoid this mangling of posts, please fix the mutilated text by hand.

Precious few.
and instead several found course to attack me because that


No, I missed that. It's a surprising reaction, since most C++ programmers have
a similar macro (usually implementing OFFSET_OF) somewhere in their toolbox.

Don't have one, never needed one.
 
C

Claudio Puviani

Jeff Schwab said:
If you're not willing to get something better than Outlook Express to
avoid this mangling of posts, please fix the mutilated text by hand.

The text gets mutilated when I hit send, not while I have a chance to edit it.
Every once in a while, if I reply to someone who wraps their text at 1
character more than my setting, weird line breaks can happen. I won't change my
newsreader or feel guilty if once every few weeks, one message turns out to be
unaesthetic.

Claudio Puviani
 
C

Claudio Puviani

Buster said:
Mark said:
Consider this:

typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

The only way this works is if I have declared a variable of type
foo...yet the compiler knows quite well what the answer to what
I am asking.

This just seems like something the compilers should be able to handle.

size_t x = sizeof foo ().b;

That's not a generic solution. It only works for types that have a visible
default constructor. Some types don't have ANY visible constructors.

Claudio Puviani
 
C

Claudio Puviani

Siemel Naran said:
Mark Rance said:
typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

Does sizeof(foo::b) work?

Think about it: is there a 'b' in the context/scope of 'foo'? Of course not. 'b'
exists in the context of an INSTANCE of 'foo', not in the context of the class
itself. If 'b' were a class static, then you could do sizeof(foo::b) because 'b'
would the exist in the context of class 'foo'.

Claudio Puviani
 
R

Rolf Magnus

Claudio said:
Siemel Naran said:
Mark Rance said:
typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

Does sizeof(foo::b) work?

Think about it: is there a 'b' in the context/scope of 'foo'?
Yes.

Of course not. 'b' exists in the context of an INSTANCE of 'foo', not
in the context of the class itself.

char (foo::* p)[5] = &foo::b;
 
C

Claudio Puviani

Rolf Magnus said:
Claudio said:
Siemel Naran said:
typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

Does sizeof(foo::b) work?

Think about it: is there a 'b' in the context/scope of 'foo'?
Yes.

Of course not. 'b' exists in the context of an INSTANCE of 'foo', not
in the context of the class itself.

char (foo::* p)[5] = &foo::b;

You're neglecting the fact that despite the misleading syntax, a
pointer-to-member is only valid in the context of the instance, not of the class.
Except in the declaration of a pointer-to-member -- where the choice of the
syntax was made for the convenience of reusing a token, not for consistency --
foo::b simply does not exist. In the case of a pointer-to-member, foo::b doesn't
refer to the variable b -- evidently, since no such variable exists without an
instance -- but rather is a notational shortcut to represent the concept of an
offset within an eventual instance. Stroustrup describes in detail why he chose
to "cheat", as he puts it, and make the offset LOOK like a pointer (when in fact
it isn't) in 13.11 of "The Design and Evolution of C++".

Claudio Puviani
 
S

Siemel Naran

Claudio Puviani said:
Siemel Naran said:
typedef struct
{
char a[10];
char b[5];
char c[3];
} foo;

Why can I not execute a statement like:

size_t x = sizeof(foo.b); ??

Does sizeof(foo::b) work?

Think about it: is there a 'b' in the context/scope of 'foo'? Of course not. 'b'
exists in the context of an INSTANCE of 'foo', not in the context of the class
itself. If 'b' were a class static, then you could do sizeof(foo::b) because 'b'
would the exist in the context of class 'foo'.

OK, I tried it on Borland 6, and it gives a compile error (but it could be
an error in the compiler). But still it seems it should work. I believe
that 'b' does exist in the instance of a foo. As foo is a class type, we're
talking of foo::b as a class type too.

Here is a version that compiles and works. But it seems a workaround of the
above concept, so I think it's a defect in the language that the idea is not
supported.


#if defined(__BORLANDC__)
#include <vcl.h>
#endif

#include <iostream>

typedef struct
{
char a[10];
char b[5];
char c[3];
double x;
} foo;

template <class Class, class T, size_t N>
size_t sizeof_member(T (Class::* member)[N])
{
return N*sizeof(T);
}

template <class Class, class T>
size_t sizeof_member(T Class::* member)
{
return sizeof(T);
}

int main(int argc, char * * argv)
{
std::cout << sizeof_member(&foo::b) << '\n'; // prints 5
std::cout << sizeof_member(&foo::x) << '\n'; // prints 8 (could be
different on different platforms)
}
 
P

puppet_sock

Jeff Schwab said:
If you're not willing to get something better than Outlook Express to
avoid this mangling of posts, please fix the mutilated text by hand.

Curious. The post you were responding to is on google with perfectly
fine line breaks, near as I can see. Don't suppose it's your newsreader
that caused the problems, do you? Nah, you're perfect.
Socks
 
J

josh

#include <iostream>

typedef struct
{
char a[10];
char b[5];
char c[3];
double x;
} foo; [...]
template <class Class, class T>
size_t sizeof_member(T Class::* member)
{
return sizeof(T);
}

or even:

template <typename class_t, typename member_t>
member_t & member_type(member_t class_t::*);

int main(void)
{
std::cout << sizeof(member_type(&foo::b)) << '\n';
std::cout << sizeof(member_type(&foo::x)) << '\n';
}

Though I guess that doesn't really make much difference.

-josh
 
J

Jeff Schwab

Curious. The post you were responding to is on google with perfectly
fine line breaks, near as I can see. Don't suppose it's your newsreader
that caused the problems, do you?
No.

Nah, you're perfect.

Why would access to a decent news reader make me "perfect?" I didn't
write my news client, and I claim no credit for it.
 
J

Jack Klein

Claudio Puviani wrote:
[snip]
sizeof gives you the size of a type (or the size of the type of the result of
an expression). 'foo.b' is neither, nor is it a valid syntactic construct. One
way to get the size is to do sizeof(((foo *)0)->b). There's no danger because
the expression never gets evaluated and so you're not actually dereferencing a
zero pointer. Only the type of the result is determined.

As an aside, did you see how much crap I got from posting my compiler's
implementation of the offsetof macro that is based on similar non-evaluated
dereferencing? I was trying to point out that there are legitimate uses for
macros, and instead several found course to attack me because that
implementation leads to undefined behavior in their mind.

There actually is a reason why one is legal and the other is not. The
sizeof operator is *required* by the standard not to evaluate its
operand. There is no such requirement on any other expression that
*appears* to dereference a null pointer. An apparent dereference is
an actual dereference as far as the standard is concerned, which
defines the operation of an abstract machine.
 
S

Siemel Naran

There was another overload.
or even:

template <typename class_t, typename member_t>
member_t & member_type(member_t class_t::*);

Your way is better as it is gives a compile time integral constant that you
can use for the size of an array (though declaring an explicit size is
usually clearer). It is also shorter (just one overload, and no need to
define the function).
 
M

MPBroida

Jeff said:
Claudio said:
Julie said:
Claudio Puviani wrote:
[snip]

sizeof gives you the size of a type (or the size of the type of the result
of

an expression). 'foo.b' is neither, nor is it a valid syntactic construct.
One

way to get the size is to do sizeof(((foo *)0)->b). There's no danger
because

the expression never gets evaluated and so you're not actually

dereferencing a
zero pointer. Only the type of the result is determined.

If you're not willing to get something better than Outlook Express to
avoid this mangling of posts, please fix the mutilated text by hand.

Julie's post didn't mangle AT ALL in my newsreader. (Netscape)
Neither did Claudio's post.

It must be your newsreader that hosed it up.

Mike
 

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
474,167
Messages
2,570,913
Members
47,455
Latest member
Delilah Code

Latest Threads

Top