Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sizeof of a class member?

55 views
Skip to first unread message

Steve

unread,
Dec 25, 2006, 6:43:50 PM12/25/06
to
Why does not the following code compile?

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! ]

Gianni Mariani

unread,
Dec 26, 2006, 7:49:05 AM12/26/06
to
Steve wrote:
> Why does not the following code compile?
>
> struct A
> {
> int a;
> const static int size_a = sizeof(a);
> };

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.

Angel Caban

unread,
Dec 26, 2006, 7:59:42 AM12/26/06
to
Steve wrote:
> Why does not the following code compile?
>
> struct A
> {
> int a;
> const static int size_a = sizeof(a);
> };
>
>

i'm pretty sure that the 'a' integer doesn't exist until an object of
struct A exists.

Ivan Novick

unread,
Dec 26, 2006, 7:53:46 AM12/26/06
to

Steve wrote:
> Why does not the following code compile?
>
> struct A
> {
> int a;
> const static int size_a = sizeof(a);
> };

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

flagos

unread,
Dec 26, 2006, 7:59:18 AM12/26/06
to
> struct A
> {
> int a;
> const static int size_a = sizeof(a);
> };

Steve:

a has to be a compile time value (static, enumerator, etc.). Try:

struct A
{
static int a;

cooleaf

unread,
Dec 26, 2006, 7:53:07 AM12/26/06
to

static member variable should initialize like below:
struct A
{
int a;
const static int size_a ;

};

const int size_a = sizeof(A);

Venkatesh

unread,
Dec 26, 2006, 3:26:24 PM12/26/06
to
This is because the size of the data member can be deduced only when it
gets defined. i.e., it can be accessed only through an object of A.

Thanks & Regards
Venkatesh

Steve

unread,
Dec 26, 2006, 3:33:26 PM12/26/06
to
Thanks Ivan and all other replies.

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

per...@gmail.com

unread,
Dec 26, 2006, 3:31:40 PM12/26/06
to
Gianni Mariani skrev:

> 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);

James Kanze

unread,
Dec 31, 2006, 1:56:02 PM12/31/06
to
Gianni Mariani wrote:
> Steve wrote:
> > Why does not the following code compile?

> > 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

James Kanze

unread,
Dec 31, 2006, 3:17:51 PM12/31/06
to
Steve wrote:
> Thanks Ivan and all other replies.

[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

Ivan Novick

unread,
Jan 5, 2007, 3:34:19 PM1/5/07
to
James Kanze wrote:

> Steve wrote:
> > How about the following code?
> > struct A
> > {
> > int a;
> > int array_a[sizeof(a)]; // not okay
> > int func() { return sizeof(a);} //okay.
> > };
> 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.

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

Gennaro Prota

unread,
Jan 5, 2007, 4:20:35 PM1/5/07
to
On 31 Dec 2006 13:56:02 -0500, James Kanze wrote:

>(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)

James Kanze

unread,
Jan 6, 2007, 5:44:28 PM1/6/07
to

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

James Kanze

unread,
Jan 6, 2007, 5:44:06 PM1/6/07
to
Gennaro Prota wrote:
> On 31 Dec 2006 13:56:02 -0500, James Kanze wrote:

> >(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

Gennaro Prota

unread,
Jan 7, 2007, 6:18:36 PM1/7/07
to
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.

___
\|||/ Gennaro Prota - For hire
(o o) https://sourceforge.net/projects/breeze/
--ooO-(_)-Ooo----- (to mail: name _ surname / yaho ! com)

--

Clark S. Cox III

unread,
Jan 8, 2007, 2:56:44 AM1/8/07
to
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 ...


--
Clark S. Cox III
clar...@gmail.com

werasm

unread,
Jan 8, 2007, 12:13:28 PM1/8/07
to

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.

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

James Kanze

unread,
Jan 8, 2007, 11:31:14 PM1/8/07
to
werasm wrote:
> 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.

> 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

unread,
Jan 9, 2007, 7:43:24 PM1/9/07
to
On 8 Jan 2007 02:56:44 -0500, Clark S. Cox III wrote:

>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)

--

0 new messages