views:

276

answers:

7

Let's say that I want to get the size in bytes or in chars for the name field from:

struct record
{
    int id;
    TCHAR name [50];
};

sizeof(record.name) does not work.

+5  A: 

In C++:

#include <iostream>
using namespace std;;

struct record
{
    int id;
    char name [50];
};

int main() {
    cout << sizeof( record::name) << endl;
}

Edit: A couple of people have pointed out that this is C++0x code, so I guess I must retract my unkind comment regarding VC++. This is not a programming construct I have ever used in my own C++ code, but I have to wonder why sizeof would not work this way in C++03? You hand it a name and it gives you the size. I'd have thought it would take some effort for it not to work. But such is the wonder of the C++ Standard :-)

anon
You forgot to return an integer.
Seth Johnson
This does not compile in VC++ 2008: error C2070: '': illegal sizeof operand
Brian R. Bondy
In C++, main() does not have to have a specific return value.
anon
If VC++ does not compile it, then VC++ has a bug.
anon
That didn't work for me (g++ 4.3.2). I had to take a sizeof of an instance of record: record myRec; sizeof(myRec.name);
stefaanv
Compiles and works perfectly for me with g++ 4.4.0
anon
2005 nor 2008 compiles it. And g++ gives this error: invalid use of non-static data member `record::name`
Brian R. Bondy
I'm using g++ version 3.4.4
Brian R. Bondy
3.4.4 is a very old version of g++ - and the whole 3.x release was notoriously buggy
anon
Ya I'm on my windows machine now with cygwin that's why I'm using 3.x currently.
Brian R. Bondy
Ditch cygwin and switch to MinGW would be my advice.
anon
OK, I'll tryMinGW.
Brian R. Bondy
great! works fine on my ubuntu-karmic with g++ v4.4.1. Result is "50".
`sizeof(record::name)` is a feature likely to be added in the next version of C++ (C++0x). It's not yet standard, nor is it widely available.
Adrian McCarthy
What Adrian said - it's a C++0x feature. Not portable C++03.
Pavel Minaev
Interesting. Is the same true for namespace qualified names?
anon
Pavel Minaev
Thanks for the explanation. It still seems strange to me that the struct/class name cannot be treated in the same way as a namespace name, but there you go.
anon
+8  A: 

The solution for this is not so pretty as you may think:

size_in_byte = sizeof(((struct record *) 0)->name)

size_in_chars = _countof(((struct record *) 0)->name)

If you want to use the second one on other platforms than Windows try:

#define _countof(array) (sizeof(array)/sizeof(array[0]))

Sorin Sbarnea
This is not necessarily portable. In C you want the "offsetof" macro. If you do use this form, please read the comments at http://c-faq.com/struct/offsetof.html.
Alok
nevermind, this won't help. Sorry for the noise.
Alok
@Alok: this is indeed not guaranteed portable, but `offsetof` is of no help here, since it computes an offset, and he needs size (and unspecified amount of padding makes it impossible to go from one to another).
Pavel Minaev
Yes, I realized it soon after I posted my silly comment (and a sillier answer to OP's question!).
Alok
A: 

In C++, the syntax is sizeof(record::name).

Edit: as Adrian pointed out, this is valid C++0x, but not C++98. In that case, sizeof(record().name) is valid as long as record is default-constructible.

C is trickier, since there is no scope-resolution operator. The best I can think of is

typedef TCHAR record_name[50];
struct record
{
    int id;
    record_name record;
};

sizeof(record_name);

Edit: or, as Sorin suggested sizeof(((struct record*)0)->name)

Mike Seymour
This is just wrong: sizeof(record::name), you're taking the sizeof of a pointer to member
rmn
Mike Seymour
rmn
The downvote is a bit harsh. `sizeof(record::name)` is being added to the standard, it's just not widely available yet.
Adrian McCarthy
C++0x is not the Standard yet, and isn't even finalized. So when referring to C++0x features, it is definitely required to explicitly identify them as such. From portability viewpoint, this is not only non-standard C++03, it's also highly non-portable (doesn't work in older g++ versions nor in VC++).
Pavel Minaev
+7  A: 

If you create an instance first, it will work.

record r;
sizeof(r.name);
Brian R. Bondy
At least, it is simple and portable.
stefaanv
sorry but this is not possible, at least not in C.
Sorin Sbarnea
+2  A: 

record is the name of a type, but record.name is not. You somehow have to access name through an instance of the struct. Sorin's answer is the usual C solution:

sizeof ((struct record*)0)->name;

This creates a pseudo-pointer to an instance (or pointer to a pseudo-instance) of struct record, then access the name member, and pass that expression to sizeof. It works because sizeof doesn't attempt to evaluate the pointer expression, it just uses it to compute the size.

John Bode
+1  A: 

You might wanna read this, as it discusses the very same issue and provides all the options mentioned in this thread, and a little more.

rmn
I might, or I might not. Perhaps you could give a hint as to why I might choose the former.
anon
Edited, sorry. :)
rmn
+1  A: 
struct record
{
    static const int kMaxNameChars=50;
    int id;
    TCHAR name [kMaxNameChars];
};


sizeof(TCHAR)*record::kMaxNameChars //"sizeof(record.name)"
//record::kMaxNameChars sufficient for many purposes.

Portable, perfectly safe and IMO being explicit about raw array length is good practice.

(edit: you might have to macro it in C, if the compiler gets upset about variable array lengths. if you do, consider defining a static const int to the value of the macro anyway!)

Matt Gordon