That is, what is the standard a compiler uses to generate a class? For example, let's say that I have class C
with members x
, y
, and z
, and I want to know the offset of z
within that class. Can I just add up the data-type sizes of the other members, like I would for a structure?

- 13,750
- 36
- 127
- 202
-
4You can't do that even for a struct. Ever heard of padding? – Jul 13 '11 at 16:43
-
2You might want to explain why you think you need to do this. – Nemo Jul 13 '11 at 16:44
-
@delnan: If by struct you mean POD, then sure, *you* can't do this, but offsetof can, and I doubt the OP is opposed to pre-existing easy solutions. – Cascabel Jul 13 '11 at 17:17
-
@Jefromi: I wasn't referring to `offsetof` in general, but to the technique OP was suggesting ("Can I just add up the data-type sizes of the other members, like I would for a structure?"). – Jul 13 '11 at 17:19
7 Answers
-
1
-
3+1 and within a single compiler alignment rules may differ depending on compilation options and pragmas... – antlersoft Jul 13 '11 at 16:45
-
-
@Fezvez: I am sorry, I should have added that link earlier, POD stands for Plain Old Data Type, Please read the link I added in the answer. – Alok Save Jul 13 '11 at 17:25
-
C++0x specifies alignment requirements. Even the previous standard specified a multitude of alignment requirements. so it isn't true to say the compiler is free to align as they choose. (C++0x Section 3.11 Alignment is a good start) – edA-qa mort-ora-y Jul 13 '11 at 18:22
-
@edA-qa mort-ora-y: The Q is not tagged `C++0x` & Can you elaborate on how standard `C++03` enforces alignment requirements? – Alok Save Jul 14 '11 at 04:31
-
The standard (pre C++0x) has many rules about which types must share alignment requirements, how compound alignment may be performed, and fundamental alignment of core types. If you read all the rules together there appears to be the implicit detail that the compiler should not be added arbitrary padding, but should only be padding to fulfill the alignment requirements of the target platform. C++0x then codifies some of these implicit rules and the common practice, in particular to provide layout guarantees which were always assumed/implied. Thus the compiler can't really *do as it chooses*. – edA-qa mort-ora-y Jul 14 '11 at 04:41
-
@edA-qa mort-ora-y: So do you mean one can find the byte alignment in NON POD types in a portable way? – Alok Save Jul 14 '11 at 04:42
-
Prior to C++0x, it's tricky, since there are no explicit layout guarantees for non-POD types, even those without virtuals. But, common convention (most, if not all compilers) is that classes without virtual functions have a clean layout like POD types, thus `offsetof` should work on these types. C++0x defines something called "Standard Layout" which enforces this type of layout -- and indeed the wording on `offsetof` is changed include "Standard Layout" types. – edA-qa mort-ora-y Jul 14 '11 at 04:54
-
@edA-qa mort-ora-y: Correct me if I am wrong, but If there is no **guaranteed** **portable** way of doing this, then what is the disagreement? – Alok Save Jul 14 '11 at 04:58
-
Well, offsetof is portable for Standard Layout types (by convention now, and guaranteed in C++0x). But my disagreement is about the compiler being free to choose alignment of members. It has some say in the padding it applies, but less choice than your first sentence would imply. – edA-qa mort-ora-y Jul 14 '11 at 05:43
You can do it programatically like this in a method of the class. Not generic but works.
offset = (unsigned char*)&(this->z) - (unsigned char*)this;
Full working example
#include <iostream>
class C
{
public:
int x;
char y;
int z;
size_t offset() const
{
return (unsigned char*)&(this->z) - (unsigned char*)this;
}
};
int main()
{
C c;
std::cerr << "Offset(cast): " << c.offset() << "\n";
}

- 8,428
- 2
- 31
- 43
You can kind-of do this by calculating the offset using a sample object. (see @bert-jan's or @sodved's answer).
However, this is dangerous! You can't treat c++ classes and structs as the regular structures you imagine them to be.
The problem is that for any given pointer-to-an-object you are given, the offset might be different!
Why? because of subclassing and multiple inheritance, additional data may be placed in the class before the regular struct members. The amount of data may differ with each different subclass of your class.
See this question: Why can't you use offsetof on non-POD structures in C++? for more details.

- 1
- 1

- 41,819
- 10
- 94
- 108
you can use &(class_name::member_name)
to get offset.

- 15,374
- 13
- 103
- 121

- 19
- 1
Have you tried offsetof()?
http://www.cplusplus.com/reference/clibrary/cstddef/offsetof/

- 1,841
- 2
- 18
- 23
-
As that site says: "Because of the extended functionality of structs in C++, in this language, the use of offsetof is restricted to POD types". – Jul 13 '11 at 16:44
Definitely not per the standard. There are compiler specific solutions which can help you infer it, though.
Microsoft has this:
#pragma pack(push,1)
struct Foo {
uint8 a;
uint32 b;
};
#pragma pack(pop)
I can relay (only by hearsay) that GCC also supports this with an extension.

- 10,444
- 2
- 30
- 46
#define _OFFSET(p_type, p_member) (size_t)(&((p_type *)NULL)->p_member)
struct a
{
int a, b;
};
cout << _OFFSET(struct a, b); // output is your offset

- 958
- 4
- 15
-
1) Why did you have to reinvent the wheel? There is a standard way to do what you did here. 2) Why did you have to use a reserved name? – R. Martinho Fernandes Jul 13 '11 at 16:53
-
However voted this down, why wouldn't this work, if the offset was calculated at run-time? Once the compiler has generated the class template for instantiation, I can't imagine why the offset would change. – Jim Fell Jul 13 '11 at 16:54
-
1This won't work because it's not valid C++: `_OFFSET` is a reserved identifier. Nevermind the undefined behavior. – R. Martinho Fernandes Jul 13 '11 at 16:57
-
I am not dereferencing it. Taking the address will not access the memory the address points to! – bert-jan Jul 13 '11 at 17:04
-
1What do you think `->` does? `a->b` is semantically equivalent to `(*a).b`. – R. Martinho Fernandes Jul 13 '11 at 17:05
-
I am not reinventing the wheel. This wheel did not exist, until ANSI C++ came and put it here. It takes 0 and adds the offset to it. – bert-jan Jul 13 '11 at 17:06
-
1@bert-jan let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/1420/discussion-between-martinho-fernandes-and-bert-jan) – R. Martinho Fernandes Jul 13 '11 at 17:06