简体   繁体   English

从c ++ struct字段获取单个字段的大小

[英]Getting the size of an indiviual field from a c++ struct field

The short version is: How do I learn the size (in bits) of an individual field of a c++ field? 简短版本是:如何学习c ++字段的单个字段的大小(以位为单位)?

To clarify, an example of the field I am talking about: 澄清一下,我所谈论的领域的一个例子:

struct Test {
    unsigned field1 : 4;  // takes up 4 bits
    unsigned field2 : 8;  // 8 bits
    unsigned field3 : 1;  // 1 bit
    unsigned field4 : 3;  // 3 bits
    unsigned field5 : 16; // 16 more to make it a 32 bit struct

    int normal_member; // normal struct variable member, 4 bytes on my system
};

Test t;
t.field1 = 1;
t.field2 = 5;
// etc.

To get the size of the entire Test object is easy, we just say 我们只是说,要获得整个Test对象的大小很简单

sizeof(Test); // returns 8, for 8 bytes total size

We can get a normal struct member through 我们可以得到一个普通的struct成员

sizeof(((Test*)0)->normal_member); // returns 4 (on my system)

I would like to know how to get the size of an individual field, say Test::field4. 我想知道如何获得单个字段的大小,比如Test :: field4。 The above example for a normal struct member does not work. 上面的普通struct成员示例不起作用。 Any ideas? 有任何想法吗? Or does someone know a reason why it cannot work? 或者有人知道它无法工作的原因吗? I am fairly convinced that sizeof will not be of help since it only returns size in bytes, but if anyone knows otherwise I'm all ears. 我相信sizeof不会有任何帮助,因为它只返回大小的字节数,但如果有人知道,我会全神贯注。

Thanks! 谢谢!

You can calculate the size at run time, fwiw, eg: 您可以在运行时计算大小,fwiw,例如:

//instantiate
Test t;
//fill all bits in the field
t.field1 = ~0;
//extract to unsigned integer
unsigned int i = t.field1;
... TODO use contents of i to calculate the bit-width of the field ...

You cannot take the sizeof a bitfield and get the number of bits. 您不能获取位域的sizeof并获取位数。

Your best bet would be use #define s or enum s: 你最好的选择是使用#define s或enum s:

struct Test {
    enum Sizes {
        sizeof_field1 = 4,
        sizeof_field2 = 8,
        sizeof_field3 = 1,
        sizeof_field4 = 3,
        sizeof_field5 = 16,
    };

    unsigned field1 : sizeof_field1;  // takes up 4 bits
    unsigned field2 : sizeof_field2;  // 8 bits
    unsigned field3 : sizeof_field3;  // 1 bit
    unsigned field4 : sizeof_field4;  // 3 bits
    unsigned field5 : sizeof_field5;  // 16 more to make it a 32 bit struct

    int normal_member; // normal struct variable member, 4 bytes on my system
};

printf("%d\n", Test::sizeof_field1); // prints 4

For the sake of consistency, I believe you can move normal_member up to the top and add an entry in Sizes using sizeof(normal_member) . 为了保持一致性,我相信您可以将normal_member移动到顶部并使用sizeof(normal_member)Sizes添加条目。 This messes with the order of your data, though. 但这会与您的数据顺序混淆。

Seems unlikely, since sizeof() is in bytes, and you want bits. 似乎不太可能,因为sizeof()以字节为单位,并且您需要位。

http://en.wikipedia.org/wiki/Sizeof http://en.wikipedia.org/wiki/Sizeof

building on the bit counting answer, you can use. 建立在位计数答案上,你可以使用。

http://www-graphics.stanford.edu/~seander/bithacks.html http://www-graphics.stanford.edu/~seander/bithacks.html

Using ChrisW's idea (nice, by the way), you can create a helper macro: 使用ChrisW的想法 (好的,顺便说一下),你可以创建一个帮助宏:

#define SIZEOF_BITFIELD(class,member,out) { \
    class tmp_;                             \
    tmp_.member = ~0;                       \
    unsigned int tmp2_ = tmp_.member;       \
    ++tmp2_;                                \
    out = log2(tmp2_);                      \
}

unsigned int log2(unsigned int x) {
    // Overflow occured.
    if(!x) {
        return sizeof(unsigned int) * CHAR_BIT;
    }

    // Some bit twiddling...  Exploiting the fact that floats use base 2 and store the exponent.  Assumes 32-bit IEEE.
    float f = (float)x;
    return (*(unsigned int *)&f >> 23) - 0x7f;
}

Usage: 用法:

size_t size;
SIZEOF_BITFIELD(Test, field1, size);  // Class of the field, field itself, output variable.

printf("%d\n", size);  // Prints 4.

My attempts to use templated functions have failed. 我尝试使用模板化函数失败了。 I'm not an expert on templates, however, so it may still be possible to have a clean method (eg sizeof_bitfield(Test::field1) ). 我不是模板方面的专家,但是,因此它仍可能有一个干净的方法(例如sizeof_bitfield(Test::field1)

This is not possible 这是不可能的

Answer to comment: Because the type is just an int, there is no 'bit' type. 回答评论:因为类型只是一个int,所以没有'bit'类型。 The bit field assignment syntax is just short hand for performing the bitwise code for reads and writes. 位字段赋值语法只是用于执行读取和写入的按位代码的简写。

I don't think you can do it. 我不认为你能做到。 If you really need the size, I suggest you use a #define (or, better yet, if possible a const variable -- I'm not sure if that's legal) as so: 如果你真的需要这个大小,我建议你使用#define (或者,更好的是,如果可能的话,一个const变量 - 我不确定这是否合法)如下:

#define TEST_FIELD1_SIZE 4
struct Test {
    unsigned field1 : TEST_FIELD1_SIZE;
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM