struct A
{
int a;
const static int size_a = sizeof(a);
};
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Comeau's try it out ( http://www.comeaucomputing.com/tryitout/ ) says:
"ComeauTest.c", line 4: error: a nonstatic member reference must be
relative to a
specific object
static const int size_a = sizeof(a);
It likes this:
struct A
{
int a;
static const int size_a = sizeof(A().a);
};
If A has no default destructor, you're outa luck.
i'm pretty sure that the 'a' integer doesn't exist until an object of
struct A exists.
The short answer: because 'a' is not static.
The long answer: according to the standard section 9.4/4: "The
definition of a static member shall not use directly the names of the
nonstatic members of its class or of a base class of its class
(including as operands of the sizeof operator)."
----
Ivan
http://www.0x4849.net
Steve:
a has to be a compile time value (static, enumerator, etc.). Try:
struct A
{
static int a;
};
const int size_a = sizeof(A);
Thanks & Regards
Venkatesh
How about the following code?
struct A
{
int a;
int array_a[sizeof(a)]; // not okay
int func() { return sizeof(a);} //okay.
};
I guess I was a little unclear on the scope of "a" and when it can be
used by sizeof. It looks like that we can't use sizeof of a non-static
class member in the class' declaration scope, but okay within its
definition scope.
In other words, the class has to be complete if we wants to get the
complie time information of its non-static data member? Not sure why
this limitation is needed.
Steve
> Steve wrote:
> > Why does not the following code compile?
> >
> > struct A
> > {
> > int a;
> > const static int size_a = sizeof(a);
> > };
> [ ... ]
> It likes this:
>
> struct A
> {
> int a;
> static const int size_a = sizeof(A().a);
> };
>
> If A has no default destructor, you're outa luck.
Then NULL pointers becomes your friend.
struct A
{
int a;
const static int size_a;
};
#define sizeof_member(TYPE, MEMBER) \
sizeof((static_cast<TYPE *> (0)->MEMBER))
const int A::size_a = sizeof_member(A, a);
> > struct A
> > {
> > int a;
> > const static int size_a = sizeof(a);
Not related to the actual question, but...
There is some disagreement among C++ programmers as to where the
const really belongs---not a few of the best C++ experts prefer
putting after the int, while some (generally older?) experts put
it before. There is, however, a very strong consensus that
storage class specifiers (such as extern or static) and typedef
should always be in the initial position. (I seem to recall
seeing somewhere that the C99 standard deprecated them
elsewhere, but I don't have a copy handy to check, and it
doesn't seem very typical of the C committee to do such a
thing.) Thus:
static int const size_a = ... ; // Preferred by most experts
or possibly:
static const int size_a = ... ; // Preferred by a few experts
But never the const before the static.
> > };
> Comeau's try it out ( http://www.comeaucomputing.com/tryitout/ ) says:
> "ComeauTest.c", line 4: error: a nonstatic member reference must be
> relative to a
> specific object
> static const int size_a = sizeof(a);
> It likes this:
> struct A
> {
> int a;
> static const int size_a = sizeof(A().a);
> };
> If A has no default destructor, you're outa luck.
Not really. Any old function which returns an A::a will do the
trick. Since the expression is not evaluated, you don't even
need a definition of the function. (And as another poster has
pointed out, you can freely dereference a null pointer without
risking undefined behavior.) You could even create a template,
if the problem came up often enough:
template< typename C, typename T >
T memberType( T C::* ) ;
and write:
static int const size_a( sizeof( memberType( &A::a ) ) ) ;
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[Note: top-posting, as you did, is considered very impolite.
In this case, you really could have cut the entire posting
you were replying to, since in addition to the thank-you,
you're really posting a new question.]
> How about the following code?
> struct A
> {
> int a;
> int array_a[sizeof(a)]; // not okay
> int func() { return sizeof(a);} //okay.
> };
> I guess I was a little unclear on the scope of "a" and when it can be
> used by sizeof. It looks like that we can't use sizeof of a non-static
> class member in the class' declaration scope, but okay within its
> definition scope.
> In other words, the class has to be complete if we wants to get the
> complie time information of its non-static data member? Not sure why
> this limitation is needed.
It's not a question of completeness. The problem is that sizeof
requires a legal expression or the name of a type. Outside of a
member function, "a" is neither. Within a non-static member
function, "a" is a legal expression equivalent to "this->a".
Logically, of course, you wouldn't expect to be able to use "a"
outside of a non-static member function, except as an operand to
sizeof (where the expression isn't evaluated). Since there are
no special rules for sizeof, except to allow type names, it
doesn't work, even though it conceivably could be made to work.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Hey wait.. on gcc 3.2.3 i get:
member `Foo::msg' is non-static but referenced as a static member
For this code:
#include <cstdio>
struct Foo
{
char msg[50];
char data[50];
};
int main(int argc, char** argv)
{
printf("sizeof = %s\n", sizeof(Foo::msg));
return 0;
}
I don't see anyting in section 5.3.3 that says you can't take size of
class member?
--
Ivan
http://www.0x4849.net
>(And as another poster has
>pointed out, you can freely dereference a null pointer without
>risking undefined behavior.)
Are you sure? Core issue 232 is still in drafting state, and core 315
(the closest closed issue :-)) doesn't apply.
___
\|||/ Gennaro Prota - For hire
(o o) https://sourceforge.net/projects/breeze/
--ooO-(_)-Ooo----- (to mail: name _ surname / yaho ! com)
As I said before, the argument of sizeof must be either the name
of a type, or a legal expression. In main(), Foo::msg is
neither. (It would be a legal expression if msg were a static
member.)
What g++ is complaining about is the fact that Foo::msg is not a
legal expression. It will complain if you use it other than in
a sizeof expression as well. For the sizeof expression to be
legal, there would have to be special text to allow it.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
> >(And as another poster has
> >pointed out, you can freely dereference a null pointer without
> >risking undefined behavior.)
> Are you sure? Core issue 232 is still in drafting state, and core 315
> (the closest closed issue :-)) doesn't apply.
You've cut some important context. In a sizeof expression, you
can freely dereference a null pointer without risking undefined
behavior, because the argument to a sizeof expression isn't
evaluated. Dereferencing a null pointer is only undefined
behavior is the expression is actually evaluated at run-time.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
>You've cut some important context. In a sizeof expression, you
>can freely dereference a null pointer without risking undefined
>behavior, because the argument to a sizeof expression isn't
>evaluated. Dereferencing a null pointer is only undefined
>behavior is the expression is actually evaluated at run-time.
Hmm, perhaps... I'm not able to back that up from the standard,
though.
___
\|||/ Gennaro Prota - For hire
(o o) https://sourceforge.net/projects/breeze/
--ooO-(_)-Ooo----- (to mail: name _ surname / yaho ! com)
--
You didn't look very hard then :)
The first two sentences describing the sizeof operator:
5.3.3 Sizeof
1 The sizeof operator yields the number of bytes in the object
representation of its operand. The operand is either an expression,
which is not evaluated ...
--
Clark S. Cox III
clar...@gmail.com
> You've cut some important context. In a sizeof expression, you
> can freely dereference a null pointer without risking undefined
> behavior, because the argument to a sizeof expression isn't
> evaluated. Dereferencing a null pointer is only undefined
> behavior is the expression is actually evaluated at run-time.
While this is true, it obscures the intent and usually leads to an
explanation in a code review, or it leads to some less experienced
programmer doubting an expression like...
sizeof(static_cast<Object*>(0)->member);
...and even removing it when in doubt.
I would prefer something like:
template <class R, class T>
R GetMemberType( R T::*member );
sizeof( GetMemberType(&Object::member) );
This leaves no one in doubt wrt. the intent (IMhO).
Regards,
Werner
> > You've cut some important context. In a sizeof expression, you
> > can freely dereference a null pointer without risking undefined
> > behavior, because the argument to a sizeof expression isn't
> > evaluated. Dereferencing a null pointer is only undefined
> > behavior is the expression is actually evaluated at run-time.
> While this is true, it obscures the intent and usually leads to an
> explanation in a code review, or it leads to some less experienced
> programmer doubting an expression like...
> sizeof(static_cast<Object*>(0)->member);
> ...and even removing it when in doubt.
Agreed. I said it was legal, not good programming practice.
> I would prefer something like:
> template <class R, class T>
> R GetMemberType( R T::*member );
> sizeof( GetMemberType(&Object::member) );
> This leaves no one in doubt wrt. the intent (IMhO).
Agreed. It's a much better solution, from all points of view.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
>Gennaro Prota wrote:
>> On 6 Jan 2007 17:44:06 -0500, James Kanze wrote:
>>
>>> You've cut some important context. In a sizeof expression, you
>>> can freely dereference a null pointer without risking undefined
>>> behavior, because the argument to a sizeof expression isn't
>>> evaluated. Dereferencing a null pointer is only undefined
>>> behavior is the expression is actually evaluated at run-time.
>>
>> Hmm, perhaps... I'm not able to back that up from the standard,
>> though.
>
>
>You didn't look very hard then :)
>
>The first two sentences describing the sizeof operator:
>
>5.3.3 Sizeof
>1 The sizeof operator yields the number of bytes in the object
>representation of its operand. The operand is either an expression,
>which is not evaluated ...
Eh, thanks. Except that the wording in [expr.unary.op]/1 doesn't allow
me to back up "dereferencing a null pointer is only undefined behavior
if the expression is actually evaluated at run-time" (in truth it
seems to me the wording makes some confusion between "expression",
which is a compile-time entity, and "pointer", so it gives little
chances to answer our question here; but no answer implies no "yes"
answer)
___
\|||/ Gennaro Prota - For hire
(o o) https://sourceforge.net/projects/breeze/
--ooO-(_)-Ooo----- (to mail: name _ surname / yaho ! com)
--